arch/x86_64: Add elf32 multiboot1 wrapper for NuttX binary

It was discovered that attempting to load x86-64 format ELF files with a multiboot1 header using the qemu `-kernel` command would result in an error, as multiboot1 only allows x86-32 format ELF files. To address this limitation, we have developed a simple x86_32 bootloader. This bootloader is designed to copy the `nuttx.bin` file to the designated memory address (`0x100000`) and then transfer control to NuttX by executing a jump instruction (`jmp 0x100000`).

Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit is contained in:
ouyangxiangzhen 2024-09-13 18:55:20 +08:00 committed by Xiang Xiao
parent 2b1da40832
commit 126221df97
5 changed files with 150 additions and 1 deletions

1
.gitignore vendored
View file

@ -49,6 +49,7 @@
/defconfig /defconfig
/Make.defs /Make.defs
/nuttx /nuttx
/nuttx32
/nuttx-* /nuttx-*
/nuttx.* /nuttx.*
/nuttx_user* /nuttx_user*

View file

@ -106,6 +106,13 @@ config ARCH_CHIP
endif # ARCH_INTEL64 endif # ARCH_INTEL64
config ARCH_MULTIBOOT1
bool "Enable ELF32/Multiboot1"
default n
---help---
This enables generating `nuttx32` and allows x86 QEMU
`-kernel` boot in multiboot1 protocol.
config ARCH_MULTIBOOT2 config ARCH_MULTIBOOT2
bool "Append multiboot2 header" bool "Append multiboot2 header"
default y default y
@ -128,6 +135,6 @@ config ARCH_PVHBOOT
bool "Append Xen PVH ELF Note" bool "Append Xen PVH ELF Note"
default y default y
---help--- ---help---
This allow x86 QEMU -kernel boot. This allows x86 QEMU `-kernel` boot in PVH protocol.
endif # ARCH_X86_64 endif # ARCH_X86_64

View file

@ -134,6 +134,13 @@ ifneq ($(CONFIG_WINDOWS_NATIVE),y)
sort > $(TOPDIR)/System.map sort > $(TOPDIR)/System.map
endif endif
ifeq ($(CONFIG_ARCH_MULTIBOOT1),y)
@echo "Generating: nuttx32 in ELF32/multiboot1"
$(Q) $(OBJCOPY) -R .realmode -R.note.* -O binary $(NUTTX) $(NUTTX).bin \
&& $(CC) -m32 -no-pie -nostdlib common/multiboot1.S \
-T common/multiboot1.ld -o $(NUTTX)32
endif
# This is part of the top-level export target # This is part of the top-level export target
export_startup: $(STARTUP_OBJS) export_startup: $(STARTUP_OBJS)

View file

@ -0,0 +1,102 @@
/****************************************************************************
* arch/x86_64/src/common/multiboot1.S
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/* Multiboot1 NuttX Naive Loader */
.set ENTRY_ADDR, 0x100000 /* NuttX Entry Address */
.set MB_FLAG_ALIGNED, 1 /* All boot modules must be loaded aligned */
.set MB_FLAG_MEMINFO, 2 /* Boot with memory maps passing */
.set MB_FLAG_VIDEO, 4 /* Enable video mode */
.set MB_FLAGS, MB_FLAG_ALIGNED | MB_FLAG_MEMINFO
.set MB_MAGIC, 0x1BADB002
.set MB_CHECKSUM, -(MB_MAGIC + MB_FLAGS)
.balign 16
.code32
.globl _start
.section ".multiboot", "ax"
header:
.align 4
.long MB_MAGIC
.long MB_FLAGS
.long MB_CHECKSUM
.long 0 /* header_addr */
.long 0 /* load_addr */
.long 0 /* load_end_addr */
.long 0 /* bss_end_addr */
.long 0 /* entry_addr */
.long 0 /* Video mode type */
.long 1024 /* Video width */
.long 768 /* Video height */
.long 32 /* Video depth */
/* NuttX bin */
.section ".bin" , "ax"
bin_start:
.incbin "../../../nuttx.bin"
.align 8
bin_size:
.long . - bin_start
/* Multiboot args */
multiboot_info_struct:
.long 0
multiboot_magic:
.long 0
.section ".text"
_start:
/* Saving multiboot args */
movl %ebx, multiboot_info_struct
movl %eax, multiboot_magic
/* memcpy(ENTRY_ADDR, bin_start, bin_size) */
movl (bin_size), %ecx
movl $bin_start, %esi
movl $ENTRY_ADDR, %edi
copy_loop:
/* Copy by bytes, make sure the addresses are not overlapped */
movb (%esi), %al
movb %al, (%edi)
inc %esi
inc %edi
loop copy_loop
/* Jump to ENTRY_ADDR */
movl (multiboot_info_struct), %ebx
movl (multiboot_magic), %eax
movl $ENTRY_ADDR, %ecx
jmp *%ecx

View file

@ -0,0 +1,32 @@
/****************************************************************************
* arch/x86_64/src/common/multiboot1.ld
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
ENTRY(_start)
SECTIONS {
. = 1M;
.text : {
*(.multiboot)
*(.bin)
*(.text)
*(.note.gnu.*)
}
}