| # |
| # Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) |
| # |
| # SPDX-License-Identifier: BSD-2-Clause |
| # |
| |
| # This module provides `DeclareRootserver` for making an executable target a rootserver |
| # and bundling it with a kernel.elf and any required loaders into an `images` directory |
| # in the top level build directory. |
| include_guard(GLOBAL) |
| |
| # Helper function for modifying the linker flags of a target to set the entry point as _sel4_start |
| function(SetSeL4Start target) |
| set_property( |
| TARGET ${target} |
| APPEND_STRING |
| PROPERTY LINK_FLAGS " -Wl,-u_sel4_start -Wl,-e_sel4_start " |
| ) |
| endfunction(SetSeL4Start) |
| |
| # We need to the real non symlinked list path in order to find the linker script that is in |
| # the common-tool directory |
| find_file( |
| TLS_ROOTSERVER tls_rootserver.lds |
| PATHS "${CMAKE_CURRENT_LIST_DIR}" |
| CMAKE_FIND_ROOT_PATH_BOTH |
| ) |
| mark_as_advanced(TLS_ROOTSERVER) |
| |
| find_file(UIMAGE_TOOL make-uimage PATHS "${CMAKE_CURRENT_LIST_DIR}" CMAKE_FIND_ROOT_PATH_BOTH) |
| mark_as_advanced(UIMAGE_TOOL) |
| include(CMakeDependentOption) |
| # NB: do not override kernel platform settings |
| #cmake_dependent_option(UseRiscVOpenSBI "Use OpenSBI." ON DEPENDS "KernelArchRiscV" OFF) |
| |
| if(UseRiscVOpenSBI) |
| set(OPENSBI_PATH "${CMAKE_SOURCE_DIR}/tools/opensbi" CACHE STRING "OpenSBI Folder location") |
| mark_as_advanced(FORCE OPENSBI_PATH) |
| endif() |
| |
| function(DeclareRootserver rootservername) |
| SetSeL4Start(${rootservername}) |
| set_property( |
| TARGET ${rootservername} |
| APPEND_STRING |
| PROPERTY LINK_FLAGS " -Wl,-T ${TLS_ROOTSERVER} " |
| ) |
| if("${KernelArch}" STREQUAL "x86") |
| set( |
| IMAGE_NAME |
| "${CMAKE_BINARY_DIR}/images/${rootservername}-image-${KernelSel4Arch}-${KernelPlatform}" |
| ) |
| set( |
| KERNEL_IMAGE_NAME |
| "${CMAKE_BINARY_DIR}/images/kernel-${KernelSel4Arch}-${KernelPlatform}" |
| ) |
| # Declare targets for building the final kernel image |
| if(Kernel64) |
| add_custom_command( |
| OUTPUT "${KERNEL_IMAGE_NAME}" |
| COMMAND |
| ${CMAKE_OBJCOPY} -O elf32-i386 $<TARGET_FILE:kernel.elf> "${KERNEL_IMAGE_NAME}" |
| VERBATIM |
| DEPENDS kernel.elf |
| COMMENT "objcopy kernel into bootable elf" |
| ) |
| else() |
| add_custom_command( |
| OUTPUT "${KERNEL_IMAGE_NAME}" |
| COMMAND cp $<TARGET_FILE:kernel.elf> "${KERNEL_IMAGE_NAME}" |
| VERBATIM |
| DEPENDS kernel.elf |
| ) |
| endif() |
| add_custom_command( |
| OUTPUT "${IMAGE_NAME}" |
| COMMAND cp $<TARGET_FILE:${rootservername}> "${IMAGE_NAME}" |
| DEPENDS ${rootservername} |
| ) |
| add_custom_target( |
| rootserver_image ALL |
| DEPENDS |
| "${IMAGE_NAME}" |
| "${KERNEL_IMAGE_NAME}" |
| kernel.elf |
| $<TARGET_FILE:${rootservername}> |
| ${rootservername} |
| ) |
| elseif(KernelArchARM OR KernelArchRiscV) |
| set( |
| IMAGE_NAME |
| "${CMAKE_BINARY_DIR}/images/${rootservername}-image-${KernelArch}-${KernelPlatform}" |
| ) |
| set(elf_target_file $<TARGET_FILE:elfloader>) |
| if(KernelArchRiscV) |
| if(UseRiscVOpenSBI) |
| # When using OpenSBI, the whole system image (usually consisting |
| # of the ELF-Loader, a device tree, the kernel, and a userland) |
| # is packaged as an OpenSBI payload. |
| |
| if("${CROSS_COMPILER_PREFIX}" STREQUAL "") |
| message(FATAL_ERROR "CROSS_COMPILER_PREFIX not set.") |
| endif() |
| |
| if("${KernelOpenSBIPlatform}" STREQUAL "") |
| message(FATAL_ERROR "KernelOpenSBIPlatform not set.") |
| endif() |
| |
| if(NOT OPENSBI_PLAT_XLEN) |
| set(OPENSBI_PLAT_XLEN "${KernelWordSize}") |
| endif() |
| |
| if(NOT OPENSBI_PLAT_ISA) |
| set(OPENSBI_PLAT_ISA "rv${OPENSBI_PLAT_XLEN}imafdc") |
| endif() |
| |
| if(NOT OPENSBI_PLAT_ABI) |
| if(Kernel32) |
| set(OPENSBI_PLAT_ABI "ilp32d") |
| else() |
| set(OPENSBI_PLAT_ABI "lp64d") |
| endif() |
| endif() |
| |
| file(GLOB_RECURSE deps) |
| set(OPENSBI_BINARY_DIR "${CMAKE_BINARY_DIR}/opensbi") |
| # OPENSBI_PLAYLOAD is a binary dump of the system image ELF |
| set(OPENSBI_PLAYLOAD "${OPENSBI_BINARY_DIR}/payload") |
| # OPENSBI_SYSTEM_IMAGE_ELF is the OpenSBI EFL file that contains |
| # our system image as firmware payload |
| set( |
| OPENSBI_SYSTEM_IMAGE_ELF |
| "${OPENSBI_BINARY_DIR}/platform/${KernelOpenSBIPlatform}/firmware/fw_payload.elf" |
| ) |
| |
| add_custom_command( |
| OUTPUT "${OPENSBI_SYSTEM_IMAGE_ELF}" |
| COMMAND mkdir -p "${OPENSBI_BINARY_DIR}" |
| COMMAND |
| make -s -C "${OPENSBI_PATH}" O="${OPENSBI_BINARY_DIR}" |
| PLATFORM="${KernelOpenSBIPlatform}" clean |
| COMMAND |
| ${CMAKE_OBJCOPY} -O binary "${elf_target_file}" "${OPENSBI_PLAYLOAD}" |
| COMMAND |
| make -C "${OPENSBI_PATH}" O="${OPENSBI_BINARY_DIR}" |
| CROSS_COMPILE=${CROSS_COMPILER_PREFIX} PLATFORM="${KernelOpenSBIPlatform}" |
| PLATFORM_RISCV_XLEN=${OPENSBI_PLAT_XLEN} |
| PLATFORM_RISCV_ISA=${OPENSBI_PLAT_ISA} |
| PLATFORM_RISCV_ABI=${OPENSBI_PLAT_ABI} FW_PAYLOAD_PATH="${OPENSBI_PLAYLOAD}" |
| DEPENDS "${elf_target_file}" elfloader ${USES_TERMINAL_DEBUG} |
| ) |
| # overwrite elf_target_file, it's no longer the ElfLoader but |
| # the OpenSBI ELF (which contains the ElfLoader as payload) |
| set(elf_target_file "${OPENSBI_SYSTEM_IMAGE_ELF}") |
| endif() |
| endif() |
| set(binary_efi_list "binary;efi") |
| if(${ElfloaderImage} IN_LIST binary_efi_list) |
| # If not an elf we construct an intermediate rule to do an objcopy to binary |
| add_custom_command( |
| OUTPUT "${IMAGE_NAME}" |
| COMMAND |
| ${CMAKE_OBJCOPY} -O binary ${elf_target_file} "${IMAGE_NAME}" |
| DEPENDS ${elf_target_file} elfloader |
| ) |
| elseif("${ElfloaderImage}" STREQUAL "uimage") |
| # Construct payload for U-Boot. |
| if(KernelSel4ArchAarch32) |
| set(UIMAGE_ARCH "arm") |
| elseif(KernelSel4ArchAarch64) |
| set(UIMAGE_ARCH "arm64") |
| else() |
| message( |
| FATAL_ERROR "uimage: Unsupported architecture: ${KernelArch}/${KernelSel4Arch}" |
| ) |
| endif() |
| |
| # Older versions of CMake don't look for readelf when initializing other binutils tools. |
| if(NOT CMAKE_READELF) |
| find_program(CMAKE_READELF NAMES ${CROSS_COMPILER_PREFIX}readelf) |
| if(NOT CMAKE_READELF) |
| message( |
| FATAL_ERROR |
| "Could not find a valid readelf program: ${CROSS_COMPILER_PREFIX}readelf. |
| ElfloaderImage type 'uimage' cannot be built." |
| ) |
| endif() |
| endif() |
| |
| add_custom_command( |
| OUTPUT "${IMAGE_NAME}" |
| COMMAND |
| ${UIMAGE_TOOL} ${CMAKE_OBJCOPY} ${CMAKE_READELF} ${elf_target_file} |
| ${UIMAGE_ARCH} ${IMAGE_NAME} |
| DEPENDS ${elf_target_file} elfloader |
| ) |
| else() |
| add_custom_command( |
| OUTPUT "${IMAGE_NAME}" |
| COMMAND |
| ${CMAKE_COMMAND} -E copy ${elf_target_file} "${IMAGE_NAME}" |
| DEPENDS ${elf_target_file} elfloader |
| ) |
| endif() |
| add_custom_target(rootserver_image ALL DEPENDS "${IMAGE_NAME}" elfloader ${rootservername}) |
| # Set the output name for the rootserver instead of leaving it to the generator. We need |
| # to do this so that we can put the rootserver image name as a property and have the |
| # elfloader pull it out using a generator expression, since generator expression cannot |
| # nest (i.e. in the expansion of $<TARGET_FILE:tgt> 'tgt' cannot itself be a generator |
| # expression. Nor can a generator expression expand to another generator expression and |
| # get expanded again. As a result we just fix the output name and location of the rootserver |
| set_property(TARGET "${rootservername}" PROPERTY OUTPUT_NAME "${rootservername}") |
| get_property(rootimage TARGET "${rootservername}" PROPERTY OUTPUT_NAME) |
| get_property(dir TARGET "${rootservername}" PROPERTY BINARY_DIR) |
| set_property(TARGET rootserver_image PROPERTY ROOTSERVER_IMAGE "${dir}/${rootimage}") |
| else() |
| message(FATAL_ERROR "Unsupported architecture.") |
| endif() |
| # Store the image and kernel image as properties |
| # We use relative paths to the build directory |
| file(RELATIVE_PATH IMAGE_NAME_REL ${CMAKE_BINARY_DIR} ${IMAGE_NAME}) |
| if(NOT "${KERNEL_IMAGE_NAME}" STREQUAL "") |
| file(RELATIVE_PATH KERNEL_IMAGE_NAME_REL ${CMAKE_BINARY_DIR} ${KERNEL_IMAGE_NAME}) |
| endif() |
| set_property(TARGET rootserver_image PROPERTY IMAGE_NAME "${IMAGE_NAME_REL}") |
| set_property(TARGET rootserver_image PROPERTY KERNEL_IMAGE_NAME "${KERNEL_IMAGE_NAME_REL}") |
| endfunction(DeclareRootserver) |