diff --git a/boards/Kconfig b/boards/Kconfig index 650ea3144c0..03064790fb6 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -56,6 +56,14 @@ config QEMU_IVSHMEM_PLAIN_MEM_SIZE device in Qemu. Note that it's in mega-bytes, so 1 means 1M for Qemu etc.. +config QEMU_UEFI_BOOT + bool "QEMU uses UEFI to boot up" + default n + depends on BUILD_OUTPUT_EFI && QEMU_TARGET && X86_64 + help + This option indicates that QEMU will use UEFI bootable method + to boot up. + # There might not be any board options, hence the optional source osource "$(BOARD_DIR)/Kconfig" endmenu diff --git a/boards/x86/qemu_x86/doc/index.rst b/boards/x86/qemu_x86/doc/index.rst index f85efa8b630..99a55cded95 100644 --- a/boards/x86/qemu_x86/doc/index.rst +++ b/boards/x86/qemu_x86/doc/index.rst @@ -113,6 +113,53 @@ QEMU, and display the following console output: Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. +For qemu_x86_64 platform, it also supports to use UEFI bootable method +to run Zephyr applications and kernel tests, but you need to set up +some environemnt configurations as follows: + +* Please install uefi-run in your system environment according to this + reference link https://github.com/Richard-W/uefi-run. + +* Please install OVMF in your system environment according to this + reference link https://github.com/tianocore/tianocore.github.io/wiki/OVMF. + +* Set system environment variable OVMF_FD_PATH, + for example: export OVMF_FD_PATH=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd + +For example, with the test "sample.basic.helloworld.uefi": + +.. code-block:: console + + export OVMF_FD_PATH=/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd + west build -b qemu_x86_64 -p auto samples/hello_world/ -DCONF_FILE=prj_uefi.conf + west build -t run + +This will build an image with the hello_world sample app, boot it on +qemu_x86_64 using UEFI, and display the following console output: + +.. code-block:: console + + UEFI Interactive Shell v2.2 + EDK II + UEFI v2.70 (EDK II, 0x00010000) + Mapping table + FS0: Alias(s):F0a:;BLK0: + PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) + BLK1: Alias(s): + PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) + Press ESC in 1 seconds to skip startup.nsh or any other key to continue. + Starting UEFI application... + *** Zephyr EFI Loader *** + Zeroing 524544 bytes of memory at 0x105000 + Copying 32768 data bytes to 0x1000 from image offset + Copying 20480 data bytes to 0x100000 from image offset 32768 + Copying 540416 data bytes to 0x185100 from image offset 53248 + Jumping to Entry Point: 0x112b (48 31 c0 48 31 d2 48) + *** Booting Zephyr OS build zephyr-v2.6.0-1472-g61810ec36d28 *** + Hello World! qemu_x86_64 + +Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. + Debugging ========= diff --git a/cmake/emu/qemu.cmake b/cmake/emu/qemu.cmake index 87f5fa6a38d..af38a2840e5 100644 --- a/cmake/emu/qemu.cmake +++ b/cmake/emu/qemu.cmake @@ -23,6 +23,19 @@ find_program( ) endif() +# We need to set up uefi-run and OVMF environment +# for testing UEFI method on qemu platforms +if(CONFIG_QEMU_UEFI_BOOT) + find_program(UEFI NAMES uefi-run REQUIRED) + if(DEFINED ENV{OVMF_FD_PATH}) + set(OVMF_FD_PATH $ENV{OVMF_FD_PATH}) + else() + message(FATAL_ERROR "Couldn't find an valid OVMF_FD_PATH.") + endif() + list(APPEND UEFI -b ${OVMF_FD_PATH} -q ${QEMU}) + set(QEMU ${UEFI}) +endif() + set(qemu_targets run debugserver @@ -242,7 +255,7 @@ elseif(QEMU_NET_STACK) endif() endif(QEMU_PIPE_STACK) -if(CONFIG_X86_64) +if(CONFIG_X86_64 AND NOT CONFIG_QEMU_UEFI_BOOT) # QEMU doesn't like 64-bit ELF files. Since we don't use any >4GB # addresses, converting it to 32-bit is safe enough for emulation. add_custom_target(qemu_image_target @@ -327,7 +340,10 @@ list(APPEND MORE_FLAGS_FOR_debugserver -s -S) # file to pass to qemu (and a "qemu_kernel_target" target to generate # it), or set QEMU_KERNEL_OPTION if they want to replace the "-kernel # ..." option entirely. -if(DEFINED QEMU_KERNEL_FILE) +if(CONFIG_QEMU_UEFI_BOOT) + set(QEMU_UEFI_OPTION ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.efi) + list(APPEND QEMU_UEFI_OPTION --) +elseif(DEFINED QEMU_KERNEL_FILE) set(QEMU_KERNEL_OPTION "-kernel;${QEMU_KERNEL_FILE}") elseif(NOT DEFINED QEMU_KERNEL_OPTION) set(QEMU_KERNEL_OPTION "-kernel;$") @@ -341,6 +357,7 @@ foreach(target ${qemu_targets}) ${PRE_QEMU_COMMANDS_FOR_${target}} COMMAND ${QEMU} + ${QEMU_UEFI_OPTION} ${QEMU_FLAGS_${ARCH}} ${QEMU_FLAGS} ${QEMU_EXTRA_FLAGS} diff --git a/samples/hello_world/prj_uefi.conf b/samples/hello_world/prj_uefi.conf new file mode 100644 index 00000000000..48ca509cdd5 --- /dev/null +++ b/samples/hello_world/prj_uefi.conf @@ -0,0 +1,4 @@ +CONFIG_QEMU_UEFI_BOOT=y +CONFIG_BUILD_OUTPUT_EFI=y +CONFIG_SRAM_SIZE=204800 +CONFIG_ACPI=y diff --git a/samples/hello_world/sample.yaml b/samples/hello_world/sample.yaml index bacc394eb45..2bdf00b9330 100644 --- a/samples/hello_world/sample.yaml +++ b/samples/hello_world/sample.yaml @@ -14,3 +14,6 @@ common: tests: sample.basic.helloworld: tags: introduction + sample.basic.helloworld.uefi: + platform_allow: qemu_x86_64 + extra_args: CONF_FILE=prj_uefi.conf