1# 2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6 7# This module provides `DeclareRootserver` for making an executable target a rootserver 8# and bundling it with a kernel.elf and any required loaders into an `images` directory 9# in the top level build directory. 10include_guard(GLOBAL) 11 12# Helper function for modifying the linker flags of a target to set the entry point as _sel4_start 13function(SetSeL4Start target) 14 set_property( 15 TARGET ${target} 16 APPEND_STRING 17 PROPERTY LINK_FLAGS " -Wl,-u_sel4_start -Wl,-e_sel4_start " 18 ) 19endfunction(SetSeL4Start) 20 21# We need to the real non symlinked list path in order to find the linker script that is in 22# the common-tool directory 23find_file( 24 TLS_ROOTSERVER tls_rootserver.lds 25 PATHS "${CMAKE_CURRENT_LIST_DIR}" 26 CMAKE_FIND_ROOT_PATH_BOTH 27) 28mark_as_advanced(TLS_ROOTSERVER) 29 30find_file(UIMAGE_TOOL make-uimage PATHS "${CMAKE_CURRENT_LIST_DIR}" CMAKE_FIND_ROOT_PATH_BOTH) 31mark_as_advanced(UIMAGE_TOOL) 32 33config_option( 34 UseRiscVBBL RISCV_BBL "Use the Berkeley Boot Loader." 35 DEFAULT ON 36 DEPENDS "KernelArchRiscV" 37) 38 39if(UseRiscVBBL) 40 set(BBL_PATH ${CMAKE_SOURCE_DIR}/tools/riscv-pk CACHE STRING "BBL Folder location") 41 mark_as_advanced(FORCE BBL_PATH) 42endif() 43 44function(DeclareRootserver rootservername) 45 SetSeL4Start(${rootservername}) 46 set_property( 47 TARGET ${rootservername} 48 APPEND_STRING 49 PROPERTY LINK_FLAGS " -Wl,-T ${TLS_ROOTSERVER} " 50 ) 51 if("${KernelArch}" STREQUAL "x86") 52 set( 53 IMAGE_NAME 54 "${CMAKE_BINARY_DIR}/images/${rootservername}-image-${KernelSel4Arch}-${KernelPlatform}" 55 ) 56 set( 57 KERNEL_IMAGE_NAME 58 "${CMAKE_BINARY_DIR}/images/kernel-${KernelSel4Arch}-${KernelPlatform}" 59 ) 60 # Declare targets for building the final kernel image 61 if(Kernel64) 62 add_custom_command( 63 OUTPUT "${KERNEL_IMAGE_NAME}" 64 COMMAND 65 ${CMAKE_OBJCOPY} -O elf32-i386 $<TARGET_FILE:kernel.elf> "${KERNEL_IMAGE_NAME}" 66 VERBATIM 67 DEPENDS kernel.elf 68 COMMENT "objcopy kernel into bootable elf" 69 ) 70 else() 71 add_custom_command( 72 OUTPUT "${KERNEL_IMAGE_NAME}" 73 COMMAND cp $<TARGET_FILE:kernel.elf> "${KERNEL_IMAGE_NAME}" 74 VERBATIM 75 DEPENDS kernel.elf 76 ) 77 endif() 78 add_custom_command( 79 OUTPUT "${IMAGE_NAME}" 80 COMMAND cp $<TARGET_FILE:${rootservername}> "${IMAGE_NAME}" 81 DEPENDS ${rootservername} 82 ) 83 add_custom_target( 84 rootserver_image ALL 85 DEPENDS 86 "${IMAGE_NAME}" 87 "${KERNEL_IMAGE_NAME}" 88 kernel.elf 89 $<TARGET_FILE:${rootservername}> 90 ${rootservername} 91 ) 92 elseif(KernelArchARM OR KernelArchRiscV) 93 set( 94 IMAGE_NAME 95 "${CMAKE_BINARY_DIR}/images/${rootservername}-image-${KernelArch}-${KernelPlatform}" 96 ) 97 set(elf_target_file $<TARGET_FILE:elfloader>) 98 if(KernelArchRiscV) 99 if(KernelSel4ArchRiscV32) 100 set(march rv32imafdc) 101 else() 102 set(march rv64imafdc) 103 endif() 104 if(UseRiscVBBL) 105 # Package up our final elf image into the Berkeley boot loader. 106 # The host string is extracted from the cross compiler setting 107 # minus the trailing '-' 108 if("${CROSS_COMPILER_PREFIX}" STREQUAL "") 109 message(FATAL_ERROR "CROSS_COMPILER_PREFIX not set.") 110 endif() 111 112 string( 113 REGEX 114 REPLACE 115 "^(.*)-$" 116 "\\1" 117 host 118 "${CROSS_COMPILER_PREFIX}" 119 ) 120 get_filename_component(host ${host} NAME) 121 file(GLOB_RECURSE deps) 122 add_custom_command( 123 OUTPUT "${CMAKE_BINARY_DIR}/bbl/bbl" 124 COMMAND mkdir -p ${CMAKE_BINARY_DIR}/bbl 125 COMMAND 126 cd ${CMAKE_BINARY_DIR}/bbl && ${BBL_PATH}/configure 127 --quiet 128 --host=${host} 129 --with-arch=${march} 130 --with-payload=${elf_target_file} 131 && make -s clean && make -s > /dev/null 132 DEPENDS ${elf_target_file} elfloader ${USES_TERMINAL_DEBUG} 133 ) 134 set(elf_target_file "${CMAKE_BINARY_DIR}/bbl/bbl") 135 endif() 136 endif() 137 set(binary_efi_list "binary;efi") 138 if(${ElfloaderImage} IN_LIST binary_efi_list) 139 # If not an elf we construct an intermediate rule to do an objcopy to binary 140 add_custom_command( 141 OUTPUT "${IMAGE_NAME}" 142 COMMAND 143 ${CMAKE_OBJCOPY} -O binary ${elf_target_file} "${IMAGE_NAME}" 144 DEPENDS ${elf_target_file} elfloader 145 ) 146 elseif("${ElfloaderImage}" STREQUAL "uimage") 147 # Construct payload for U-Boot. 148 149 if("${KernelArmSel4Arch}" STREQUAL "aarch32") 150 set(UIMAGE_ARCH "arm") 151 elseif(KernelSel4ArchAarch64) 152 set(UIMAGE_ARCH "arm64") 153 else() 154 message(FATAL_ERROR "uimage: Unsupported architecture: ${KernelArch}") 155 endif() 156 157 add_custom_command( 158 OUTPUT "${IMAGE_NAME}" 159 COMMAND 160 ${UIMAGE_TOOL} ${CMAKE_OBJCOPY} ${elf_target_file} ${UIMAGE_ARCH} ${IMAGE_NAME} 161 DEPENDS ${elf_target_file} elfloader 162 ) 163 else() 164 add_custom_command( 165 OUTPUT "${IMAGE_NAME}" 166 COMMAND 167 ${CMAKE_COMMAND} -E copy ${elf_target_file} "${IMAGE_NAME}" 168 DEPENDS ${elf_target_file} elfloader 169 ) 170 endif() 171 add_custom_target(rootserver_image ALL DEPENDS "${IMAGE_NAME}" elfloader ${rootservername}) 172 # Set the output name for the rootserver instead of leaving it to the generator. We need 173 # to do this so that we can put the rootserver image name as a property and have the 174 # elfloader pull it out using a generator expression, since generator expression cannot 175 # nest (i.e. in the expansion of $<TARGET_FILE:tgt> 'tgt' cannot itself be a generator 176 # expression. Nor can a generator expression expand to another generator expression and 177 # get expanded again. As a result we just fix the output name and location of the rootserver 178 set_property(TARGET "${rootservername}" PROPERTY OUTPUT_NAME "${rootservername}") 179 get_property(rootimage TARGET "${rootservername}" PROPERTY OUTPUT_NAME) 180 get_property(dir TARGET "${rootservername}" PROPERTY BINARY_DIR) 181 set_property(TARGET rootserver_image PROPERTY ROOTSERVER_IMAGE "${dir}/${rootimage}") 182 else() 183 message(FATAL_ERROR "Unsupported architecture.") 184 endif() 185 # Store the image and kernel image as properties 186 # We use relative paths to the build directory 187 file(RELATIVE_PATH IMAGE_NAME_REL ${CMAKE_BINARY_DIR} ${IMAGE_NAME}) 188 if(NOT "${KERNEL_IMAGE_NAME}" STREQUAL "") 189 file(RELATIVE_PATH KERNEL_IMAGE_NAME_REL ${CMAKE_BINARY_DIR} ${KERNEL_IMAGE_NAME}) 190 endif() 191 set_property(TARGET rootserver_image PROPERTY IMAGE_NAME "${IMAGE_NAME_REL}") 192 set_property(TARGET rootserver_image PROPERTY KERNEL_IMAGE_NAME "${KERNEL_IMAGE_NAME_REL}") 193endfunction(DeclareRootserver) 194