hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/hw/loongarch/boot.h | 17 +++++++++++++++++ 2 files changed, 62 insertions(+)
Many distros are shipping raw kernel images (i.e. vmlinux.efi).
Support booting such image by parsing header as per Linux's
specification [1].
[1]: https://docs.kernel.org/arch/loongarch/booting.html
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
It is based on my previous booting protocol patch
---
hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
include/hw/loongarch/boot.h | 17 +++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
--- a/hw/loongarch/boot.c
+++ b/hw/loongarch/boot.c
@@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
}
+static int64_t get_linux_image_info(struct loongarch_boot_info *info,
+ uint64_t *kernel_entry,
+ uint64_t *kernel_low,
+ uint64_t *kernel_high)
+{
+ int fd;
+ struct loongarch_linux_hdr hdr;
+ int64_t kernel_size = -1;
+
+ fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ return -1;
+ }
+
+ if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
+ close(fd);
+ return -1;
+ }
+
+ if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
+ le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
+ close(fd);
+ return -1;
+ }
+
+ *kernel_entry = le64_to_cpu(hdr.kernel_entry);
+ /* Early kernel versions may have those fields in virtual address */
+ *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
+ *kernel_low = le64_to_cpu(hdr.load_offset);
+ *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
+ kernel_size = le64_to_cpu(hdr.kernel_size);
+ *kernel_high = *kernel_low + kernel_size;
+
+ close(fd);
+ return kernel_size;
+}
+
static int64_t load_kernel_info(struct loongarch_boot_info *info)
{
uint64_t kernel_entry, kernel_low, kernel_high;
@@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
&kernel_entry, &kernel_low,
&kernel_high, NULL, 0,
EM_LOONGARCH, 1, 0);
+ if (kernel_size < 0) {
+ kernel_size = get_linux_image_info(info, &kernel_entry,
+ &kernel_low, &kernel_high);
+ if (kernel_size >= 0) {
+ kernel_size = load_image_targphys(info->kernel_filename,
+ kernel_low, kernel_size);
+ }
+ }
if (kernel_size < 0) {
error_report("could not load kernel '%s': %s",
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
--- a/include/hw/loongarch/boot.h
+++ b/include/hw/loongarch/boot.h
@@ -8,6 +8,23 @@
#ifndef HW_LOONGARCH_BOOT_H
#define HW_LOONGARCH_BOOT_H
+/* Linux Image Format */
+#define LINUX_PE_MAGIC 0x818223cd
+#define MZ_MAGIC 0x5a4d /* "MZ" */
+
+struct loongarch_linux_hdr {
+ uint32_t mz_magic;
+ uint32_t res0;
+ uint64_t kernel_entry;
+ uint64_t kernel_size;
+ uint64_t load_offset;
+ uint64_t res1;
+ uint64_t res2;
+ uint64_t res3;
+ uint32_t linux_pe_magic;
+ uint32_t pe_header_offset;
+} QEMU_PACKED;
+
/* UEFI 2.10 */
#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
#define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
---
base-commit: c69612063e1844b76ac01e3a781b979548c3585c
change-id: 20241222-la-direct-kernel-boot-c598264710e7
Best regards,
--
Jiaxun Yang <jiaxun.yang@flygoat.com>
On 2024/12/23 上午8:30, Jiaxun Yang wrote:
> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>
> Support booting such image by parsing header as per Linux's
> specification [1].
>
> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> It is based on my previous booting protocol patch
> ---
> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> include/hw/loongarch/boot.h | 17 +++++++++++++++++
> 2 files changed, 62 insertions(+)
>
> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
> --- a/hw/loongarch/boot.c
> +++ b/hw/loongarch/boot.c
> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> }
>
> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
> + uint64_t *kernel_entry,
> + uint64_t *kernel_low,
> + uint64_t *kernel_high)
> +{
> + int fd;
> + struct loongarch_linux_hdr hdr;
> + int64_t kernel_size = -1;
> +
> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
> + if (fd < 0) {
> + return -1;
> + }
> +
> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
> + close(fd);
> + return -1;
> + }
> +
> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
> + close(fd);
> + return -1;
> + }
> +
> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
> + /* Early kernel versions may have those fields in virtual address */
> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> + *kernel_low = le64_to_cpu(hdr.load_offset);
> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> + kernel_size = le64_to_cpu(hdr.kernel_size);
> + *kernel_high = *kernel_low + kernel_size;
> +
> + close(fd);
> + return kernel_size;
> +}
> +
> static int64_t load_kernel_info(struct loongarch_boot_info *info)
> {
> uint64_t kernel_entry, kernel_low, kernel_high;
> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
> &kernel_entry, &kernel_low,
> &kernel_high, NULL, 0,
> EM_LOONGARCH, 1, 0);
> + if (kernel_size < 0) {
> + kernel_size = get_linux_image_info(info, &kernel_entry,
> + &kernel_low, &kernel_high);
> + if (kernel_size >= 0) {
> + kernel_size = load_image_targphys(info->kernel_filename,
> + kernel_low, kernel_size);
> + }
Can we read file header file firstly?
If it is ELFMAG, load_elf is called.
If it is EFI_PE_MSDOS_MAGIC, check zimg magic in linux_efi_zboot_header,
else loongarch_linux_hdr for plain image if zimg does not match.
Regards
Bibo Mao
> + }
>
> if (kernel_size < 0) {
> error_report("could not load kernel '%s': %s",
> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
> --- a/include/hw/loongarch/boot.h
> +++ b/include/hw/loongarch/boot.h
> @@ -8,6 +8,23 @@
> #ifndef HW_LOONGARCH_BOOT_H
> #define HW_LOONGARCH_BOOT_H
>
> +/* Linux Image Format */
> +#define LINUX_PE_MAGIC 0x818223cd
> +#define MZ_MAGIC 0x5a4d /* "MZ" */
> +
> +struct loongarch_linux_hdr {
> + uint32_t mz_magic;
> + uint32_t res0;
> + uint64_t kernel_entry;
> + uint64_t kernel_size;
> + uint64_t load_offset;
> + uint64_t res1;
> + uint64_t res2;
> + uint64_t res3;
> + uint32_t linux_pe_magic;
> + uint32_t pe_header_offset;
> +} QEMU_PACKED;
> +
> /* UEFI 2.10 */
> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>
> ---
> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>
> Best regards,
>
在2024年12月24日十二月 上午4:03,bibo mao写道:
> On 2024/12/23 上午8:30, Jiaxun Yang wrote:
>> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>>
>> Support booting such image by parsing header as per Linux's
>> specification [1].
>>
>> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>>
>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>> ---
>> It is based on my previous booting protocol patch
>> ---
>> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>> include/hw/loongarch/boot.h | 17 +++++++++++++++++
>> 2 files changed, 62 insertions(+)
>>
>> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
>> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
>> --- a/hw/loongarch/boot.c
>> +++ b/hw/loongarch/boot.c
>> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
>> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> }
>>
>> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
>> + uint64_t *kernel_entry,
>> + uint64_t *kernel_low,
>> + uint64_t *kernel_high)
>> +{
>> + int fd;
>> + struct loongarch_linux_hdr hdr;
>> + int64_t kernel_size = -1;
>> +
>> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
>> + if (fd < 0) {
>> + return -1;
>> + }
>> +
>> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
>> + close(fd);
>> + return -1;
>> + }
>> +
>> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
>> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
>> + close(fd);
>> + return -1;
>> + }
>> +
>> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
>> + /* Early kernel versions may have those fields in virtual address */
>> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> + *kernel_low = le64_to_cpu(hdr.load_offset);
>> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> + kernel_size = le64_to_cpu(hdr.kernel_size);
>> + *kernel_high = *kernel_low + kernel_size;
>> +
>> + close(fd);
>> + return kernel_size;
>> +}
>> +
>> static int64_t load_kernel_info(struct loongarch_boot_info *info)
>> {
>> uint64_t kernel_entry, kernel_low, kernel_high;
>> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
>> &kernel_entry, &kernel_low,
>> &kernel_high, NULL, 0,
>> EM_LOONGARCH, 1, 0);
>> + if (kernel_size < 0) {
>> + kernel_size = get_linux_image_info(info, &kernel_entry,
>> + &kernel_low, &kernel_high);
>> + if (kernel_size >= 0) {
>> + kernel_size = load_image_targphys(info->kernel_filename,
>> + kernel_low, kernel_size);
>> + }
> Can we read file header file firstly?
> If it is ELFMAG, load_elf is called.
>
> If it is EFI_PE_MSDOS_MAGIC, check zimg magic in linux_efi_zboot_header,
> else loongarch_linux_hdr for plain image if zimg does not match.
I'd say as checking will be done by load_elf, the fallback path makes more
sense here.
See similar design on Arm's arm_setup_direct_kernel_boot.
But you are right, I should handle vmlinuz.efi with linux_efi_zboot_header
as well.
>
> Regards
> Bibo Mao
>
>> + }
[...]
--
- Jiaxun
Sorry, I do not know the background.
Now kernel image with EFI format can boot if uefi bios is provided.
What is this patch to do? is it to direct boot kernel with EFI format
without UEFI bios parameter?
Regards
Bibo Mao
On 2024/12/23 上午8:30, Jiaxun Yang wrote:
> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>
> Support booting such image by parsing header as per Linux's
> specification [1].
>
> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
> It is based on my previous booting protocol patch
> ---
> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
> include/hw/loongarch/boot.h | 17 +++++++++++++++++
> 2 files changed, 62 insertions(+)
>
> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
> --- a/hw/loongarch/boot.c
> +++ b/hw/loongarch/boot.c
> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> }
>
> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
> + uint64_t *kernel_entry,
> + uint64_t *kernel_low,
> + uint64_t *kernel_high)
> +{
> + int fd;
> + struct loongarch_linux_hdr hdr;
> + int64_t kernel_size = -1;
> +
> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
> + if (fd < 0) {
> + return -1;
> + }
> +
> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
> + close(fd);
> + return -1;
> + }
> +
> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
> + close(fd);
> + return -1;
> + }
> +
> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
> + /* Early kernel versions may have those fields in virtual address */
> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> + *kernel_low = le64_to_cpu(hdr.load_offset);
> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
> + kernel_size = le64_to_cpu(hdr.kernel_size);
> + *kernel_high = *kernel_low + kernel_size;
> +
> + close(fd);
> + return kernel_size;
> +}
> +
> static int64_t load_kernel_info(struct loongarch_boot_info *info)
> {
> uint64_t kernel_entry, kernel_low, kernel_high;
> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
> &kernel_entry, &kernel_low,
> &kernel_high, NULL, 0,
> EM_LOONGARCH, 1, 0);
> + if (kernel_size < 0) {
> + kernel_size = get_linux_image_info(info, &kernel_entry,
> + &kernel_low, &kernel_high);
> + if (kernel_size >= 0) {
> + kernel_size = load_image_targphys(info->kernel_filename,
> + kernel_low, kernel_size);
> + }
> + }
>
> if (kernel_size < 0) {
> error_report("could not load kernel '%s': %s",
> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
> --- a/include/hw/loongarch/boot.h
> +++ b/include/hw/loongarch/boot.h
> @@ -8,6 +8,23 @@
> #ifndef HW_LOONGARCH_BOOT_H
> #define HW_LOONGARCH_BOOT_H
>
> +/* Linux Image Format */
> +#define LINUX_PE_MAGIC 0x818223cd
> +#define MZ_MAGIC 0x5a4d /* "MZ" */
> +
> +struct loongarch_linux_hdr {
> + uint32_t mz_magic;
> + uint32_t res0;
> + uint64_t kernel_entry;
> + uint64_t kernel_size;
> + uint64_t load_offset;
> + uint64_t res1;
> + uint64_t res2;
> + uint64_t res3;
> + uint32_t linux_pe_magic;
> + uint32_t pe_header_offset;
> +} QEMU_PACKED;
> +
> /* UEFI 2.10 */
> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>
> ---
> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>
> Best regards,
>
在2024年12月24日十二月 上午12:56,bibo mao写道:
> Sorry, I do not know the background.
> Now kernel image with EFI format can boot if uefi bios is provided.
>
> What is this patch to do? is it to direct boot kernel with EFI format
> without UEFI bios parameter?
Yes, it’s now capable for booting vmlinux.efi without BIOS, as well as raw kernel built without EFI STUB.
Thanks
>
> Regards
> Bibo Mao
>
> On 2024/12/23 上午8:30, Jiaxun Yang wrote:
>> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>>
>> Support booting such image by parsing header as per Linux's
>> specification [1].
>>
>> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>>
>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>> ---
>> It is based on my previous booting protocol patch
>> ---
>> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>> include/hw/loongarch/boot.h | 17 +++++++++++++++++
>> 2 files changed, 62 insertions(+)
>>
>> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
>> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
>> --- a/hw/loongarch/boot.c
>> +++ b/hw/loongarch/boot.c
>> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
>> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> }
>>
>> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
>> + uint64_t *kernel_entry,
>> + uint64_t *kernel_low,
>> + uint64_t *kernel_high)
>> +{
>> + int fd;
>> + struct loongarch_linux_hdr hdr;
>> + int64_t kernel_size = -1;
>> +
>> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
>> + if (fd < 0) {
>> + return -1;
>> + }
>> +
>> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
>> + close(fd);
>> + return -1;
>> + }
>> +
>> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
>> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
>> + close(fd);
>> + return -1;
>> + }
>> +
>> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
>> + /* Early kernel versions may have those fields in virtual address */
>> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> + *kernel_low = le64_to_cpu(hdr.load_offset);
>> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>> + kernel_size = le64_to_cpu(hdr.kernel_size);
>> + *kernel_high = *kernel_low + kernel_size;
>> +
>> + close(fd);
>> + return kernel_size;
>> +}
>> +
>> static int64_t load_kernel_info(struct loongarch_boot_info *info)
>> {
>> uint64_t kernel_entry, kernel_low, kernel_high;
>> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
>> &kernel_entry, &kernel_low,
>> &kernel_high, NULL, 0,
>> EM_LOONGARCH, 1, 0);
>> + if (kernel_size < 0) {
>> + kernel_size = get_linux_image_info(info, &kernel_entry,
>> + &kernel_low, &kernel_high);
>> + if (kernel_size >= 0) {
>> + kernel_size = load_image_targphys(info->kernel_filename,
>> + kernel_low, kernel_size);
>> + }
>> + }
>>
>> if (kernel_size < 0) {
>> error_report("could not load kernel '%s': %s",
>> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
>> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
>> --- a/include/hw/loongarch/boot.h
>> +++ b/include/hw/loongarch/boot.h
>> @@ -8,6 +8,23 @@
>> #ifndef HW_LOONGARCH_BOOT_H
>> #define HW_LOONGARCH_BOOT_H
>>
>> +/* Linux Image Format */
>> +#define LINUX_PE_MAGIC 0x818223cd
>> +#define MZ_MAGIC 0x5a4d /* "MZ" */
>> +
>> +struct loongarch_linux_hdr {
>> + uint32_t mz_magic;
>> + uint32_t res0;
>> + uint64_t kernel_entry;
>> + uint64_t kernel_size;
>> + uint64_t load_offset;
>> + uint64_t res1;
>> + uint64_t res2;
>> + uint64_t res3;
>> + uint32_t linux_pe_magic;
>> + uint32_t pe_header_offset;
>> +} QEMU_PACKED;
>> +
>> /* UEFI 2.10 */
>> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
>> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>>
>> ---
>> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
>> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>>
>> Best regards,
>>
--
- Jiaxun
On 2024/12/24 上午9:15, Jiaxun Yang wrote:
>
>
> 在2024年12月24日十二月 上午12:56,bibo mao写道:
>> Sorry, I do not know the background.
>> Now kernel image with EFI format can boot if uefi bios is provided.
>>
>> What is this patch to do? is it to direct boot kernel with EFI format
>> without UEFI bios parameter?
>
> Yes, it’s now capable for booting vmlinux.efi without BIOS, as well as raw kernel built without EFI STUB.
Is efi boottime service used by vmlinux.efi? such as
handle_protocol/allocate_pages etc.
Regards
Bibo Mao
>
> Thanks
>
>>
>> Regards
>> Bibo Mao
>>
>> On 2024/12/23 上午8:30, Jiaxun Yang wrote:
>>> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>>>
>>> Support booting such image by parsing header as per Linux's
>>> specification [1].
>>>
>>> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>>>
>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> ---
>>> It is based on my previous booting protocol patch
>>> ---
>>> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>>> include/hw/loongarch/boot.h | 17 +++++++++++++++++
>>> 2 files changed, 62 insertions(+)
>>>
>>> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
>>> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
>>> --- a/hw/loongarch/boot.c
>>> +++ b/hw/loongarch/boot.c
>>> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
>>> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>> }
>>>
>>> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
>>> + uint64_t *kernel_entry,
>>> + uint64_t *kernel_low,
>>> + uint64_t *kernel_high)
>>> +{
>>> + int fd;
>>> + struct loongarch_linux_hdr hdr;
>>> + int64_t kernel_size = -1;
>>> +
>>> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
>>> + if (fd < 0) {
>>> + return -1;
>>> + }
>>> +
>>> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
>>> + close(fd);
>>> + return -1;
>>> + }
>>> +
>>> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
>>> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
>>> + close(fd);
>>> + return -1;
>>> + }
>>> +
>>> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
>>> + /* Early kernel versions may have those fields in virtual address */
>>> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>> + *kernel_low = le64_to_cpu(hdr.load_offset);
>>> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>> + kernel_size = le64_to_cpu(hdr.kernel_size);
>>> + *kernel_high = *kernel_low + kernel_size;
>>> +
>>> + close(fd);
>>> + return kernel_size;
>>> +}
>>> +
>>> static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>> {
>>> uint64_t kernel_entry, kernel_low, kernel_high;
>>> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>> &kernel_entry, &kernel_low,
>>> &kernel_high, NULL, 0,
>>> EM_LOONGARCH, 1, 0);
>>> + if (kernel_size < 0) {
>>> + kernel_size = get_linux_image_info(info, &kernel_entry,
>>> + &kernel_low, &kernel_high);
>>> + if (kernel_size >= 0) {
>>> + kernel_size = load_image_targphys(info->kernel_filename,
>>> + kernel_low, kernel_size);
>>> + }
>>> + }
>>>
>>> if (kernel_size < 0) {
>>> error_report("could not load kernel '%s': %s",
>>> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
>>> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
>>> --- a/include/hw/loongarch/boot.h
>>> +++ b/include/hw/loongarch/boot.h
>>> @@ -8,6 +8,23 @@
>>> #ifndef HW_LOONGARCH_BOOT_H
>>> #define HW_LOONGARCH_BOOT_H
>>>
>>> +/* Linux Image Format */
>>> +#define LINUX_PE_MAGIC 0x818223cd
>>> +#define MZ_MAGIC 0x5a4d /* "MZ" */
>>> +
>>> +struct loongarch_linux_hdr {
>>> + uint32_t mz_magic;
>>> + uint32_t res0;
>>> + uint64_t kernel_entry;
>>> + uint64_t kernel_size;
>>> + uint64_t load_offset;
>>> + uint64_t res1;
>>> + uint64_t res2;
>>> + uint64_t res3;
>>> + uint32_t linux_pe_magic;
>>> + uint32_t pe_header_offset;
>>> +} QEMU_PACKED;
>>> +
>>> /* UEFI 2.10 */
>>> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
>>> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>>>
>>> ---
>>> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
>>> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>>>
>>> Best regards,
>>>
>
在2024年12月24日十二月 上午1:25,bibo mao写道:
> On 2024/12/24 上午9:15, Jiaxun Yang wrote:
>>
>>
>> 在2024年12月24日十二月 上午12:56,bibo mao写道:
>>> Sorry, I do not know the background.
>>> Now kernel image with EFI format can boot if uefi bios is provided.
>>>
>>> What is this patch to do? is it to direct boot kernel with EFI format
>>> without UEFI bios parameter?
>>
>> Yes, it’s now capable for booting vmlinux.efi without BIOS, as well as raw kernel built without EFI STUB.
> Is efi boottime service used by vmlinux.efi? such as
> handle_protocol/allocate_pages etc.
Short answer: no.
To explain, we are jumping directly to kernel’s
entry instead of EFISTUB entry.
So it basically it works in the same manner as ELF booting, kernel won’t call EFI service if non-EFI booting environment is detected via a0 argument.
Thanks
>
> Regards
> Bibo Mao
>>
>> Thanks
>>
>>>
>>> Regards
>>> Bibo Mao
>>>
>>> On 2024/12/23 上午8:30, Jiaxun Yang wrote:
>>>> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>>>>
>>>> Support booting such image by parsing header as per Linux's
>>>> specification [1].
>>>>
>>>> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>>>>
>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>> ---
>>>> It is based on my previous booting protocol patch
>>>> ---
>>>> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>>>> include/hw/loongarch/boot.h | 17 +++++++++++++++++
>>>> 2 files changed, 62 insertions(+)
>>>>
>>>> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
>>>> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
>>>> --- a/hw/loongarch/boot.c
>>>> +++ b/hw/loongarch/boot.c
>>>> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
>>>> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>> }
>>>>
>>>> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
>>>> + uint64_t *kernel_entry,
>>>> + uint64_t *kernel_low,
>>>> + uint64_t *kernel_high)
>>>> +{
>>>> + int fd;
>>>> + struct loongarch_linux_hdr hdr;
>>>> + int64_t kernel_size = -1;
>>>> +
>>>> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
>>>> + if (fd < 0) {
>>>> + return -1;
>>>> + }
>>>> +
>>>> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
>>>> + close(fd);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
>>>> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
>>>> + close(fd);
>>>> + return -1;
>>>> + }
>>>> +
>>>> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
>>>> + /* Early kernel versions may have those fields in virtual address */
>>>> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>> + *kernel_low = le64_to_cpu(hdr.load_offset);
>>>> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>> + kernel_size = le64_to_cpu(hdr.kernel_size);
>>>> + *kernel_high = *kernel_low + kernel_size;
>>>> +
>>>> + close(fd);
>>>> + return kernel_size;
>>>> +}
>>>> +
>>>> static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>>> {
>>>> uint64_t kernel_entry, kernel_low, kernel_high;
>>>> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>>> &kernel_entry, &kernel_low,
>>>> &kernel_high, NULL, 0,
>>>> EM_LOONGARCH, 1, 0);
>>>> + if (kernel_size < 0) {
>>>> + kernel_size = get_linux_image_info(info, &kernel_entry,
>>>> + &kernel_low, &kernel_high);
>>>> + if (kernel_size >= 0) {
>>>> + kernel_size = load_image_targphys(info->kernel_filename,
>>>> + kernel_low, kernel_size);
>>>> + }
>>>> + }
>>>>
>>>> if (kernel_size < 0) {
>>>> error_report("could not load kernel '%s': %s",
>>>> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
>>>> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
>>>> --- a/include/hw/loongarch/boot.h
>>>> +++ b/include/hw/loongarch/boot.h
>>>> @@ -8,6 +8,23 @@
>>>> #ifndef HW_LOONGARCH_BOOT_H
>>>> #define HW_LOONGARCH_BOOT_H
>>>>
>>>> +/* Linux Image Format */
>>>> +#define LINUX_PE_MAGIC 0x818223cd
>>>> +#define MZ_MAGIC 0x5a4d /* "MZ" */
>>>> +
>>>> +struct loongarch_linux_hdr {
>>>> + uint32_t mz_magic;
>>>> + uint32_t res0;
>>>> + uint64_t kernel_entry;
>>>> + uint64_t kernel_size;
>>>> + uint64_t load_offset;
>>>> + uint64_t res1;
>>>> + uint64_t res2;
>>>> + uint64_t res3;
>>>> + uint32_t linux_pe_magic;
>>>> + uint32_t pe_header_offset;
>>>> +} QEMU_PACKED;
>>>> +
>>>> /* UEFI 2.10 */
>>>> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
>>>> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>>>>
>>>> ---
>>>> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
>>>> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>>>>
>>>> Best regards,
>>>>
>>
--
- Jiaxun
On 2024/12/24 上午10:31, Jiaxun Yang wrote:
>
>
> 在2024年12月24日十二月 上午1:25,bibo mao写道:
>> On 2024/12/24 上午9:15, Jiaxun Yang wrote:
>>>
>>>
>>> 在2024年12月24日十二月 上午12:56,bibo mao写道:
>>>> Sorry, I do not know the background.
>>>> Now kernel image with EFI format can boot if uefi bios is provided.
>>>>
>>>> What is this patch to do? is it to direct boot kernel with EFI format
>>>> without UEFI bios parameter?
>>>
>>> Yes, it’s now capable for booting vmlinux.efi without BIOS, as well as raw kernel built without EFI STUB.
>> Is efi boottime service used by vmlinux.efi? such as
>> handle_protocol/allocate_pages etc.
>
> Short answer: no.
>
> To explain, we are jumping directly to kernel’s
> entry instead of EFISTUB entry.
>
> So it basically it works in the same manner as ELF booting, kernel won’t call EFI service if non-EFI booting environment is detected via a0 argument.
That is wonderful, please add this in the note.
Regards
Bibo Mao
>
> Thanks
>>
>> Regards
>> Bibo Mao
>>>
>>> Thanks
>>>
>>>>
>>>> Regards
>>>> Bibo Mao
>>>>
>>>> On 2024/12/23 上午8:30, Jiaxun Yang wrote:
>>>>> Many distros are shipping raw kernel images (i.e. vmlinux.efi).
>>>>>
>>>>> Support booting such image by parsing header as per Linux's
>>>>> specification [1].
>>>>>
>>>>> [1]: https://docs.kernel.org/arch/loongarch/booting.html
>>>>>
>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> ---
>>>>> It is based on my previous booting protocol patch
>>>>> ---
>>>>> hw/loongarch/boot.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>>>>> include/hw/loongarch/boot.h | 17 +++++++++++++++++
>>>>> 2 files changed, 62 insertions(+)
>>>>>
>>>>> diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
>>>>> index 93847b0eaf8e50ce1a990b91267780e6785e1c2f..5bc889c51fafa9c6d37426b9bee9709c12183927 100644
>>>>> --- a/hw/loongarch/boot.c
>>>>> +++ b/hw/loongarch/boot.c
>>>>> @@ -260,6 +260,43 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
>>>>> return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>>> }
>>>>>
>>>>> +static int64_t get_linux_image_info(struct loongarch_boot_info *info,
>>>>> + uint64_t *kernel_entry,
>>>>> + uint64_t *kernel_low,
>>>>> + uint64_t *kernel_high)
>>>>> +{
>>>>> + int fd;
>>>>> + struct loongarch_linux_hdr hdr;
>>>>> + int64_t kernel_size = -1;
>>>>> +
>>>>> + fd = open(info->kernel_filename, O_RDONLY | O_BINARY);
>>>>> + if (fd < 0) {
>>>>> + return -1;
>>>>> + }
>>>>> +
>>>>> + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
>>>>> + close(fd);
>>>>> + return -1;
>>>>> + }
>>>>> +
>>>>> + if ((le32_to_cpu(hdr.mz_magic) & 0xffff) != MZ_MAGIC ||
>>>>> + le32_to_cpu(hdr.linux_pe_magic) != LINUX_PE_MAGIC) {
>>>>> + close(fd);
>>>>> + return -1;
>>>>> + }
>>>>> +
>>>>> + *kernel_entry = le64_to_cpu(hdr.kernel_entry);
>>>>> + /* Early kernel versions may have those fields in virtual address */
>>>>> + *kernel_entry &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>>> + *kernel_low = le64_to_cpu(hdr.load_offset);
>>>>> + *kernel_low &= MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
>>>>> + kernel_size = le64_to_cpu(hdr.kernel_size);
>>>>> + *kernel_high = *kernel_low + kernel_size;
>>>>> +
>>>>> + close(fd);
>>>>> + return kernel_size;
>>>>> +}
>>>>> +
>>>>> static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>>>> {
>>>>> uint64_t kernel_entry, kernel_low, kernel_high;
>>>>> @@ -270,6 +307,14 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
>>>>> &kernel_entry, &kernel_low,
>>>>> &kernel_high, NULL, 0,
>>>>> EM_LOONGARCH, 1, 0);
>>>>> + if (kernel_size < 0) {
>>>>> + kernel_size = get_linux_image_info(info, &kernel_entry,
>>>>> + &kernel_low, &kernel_high);
>>>>> + if (kernel_size >= 0) {
>>>>> + kernel_size = load_image_targphys(info->kernel_filename,
>>>>> + kernel_low, kernel_size);
>>>>> + }
>>>>> + }
>>>>>
>>>>> if (kernel_size < 0) {
>>>>> error_report("could not load kernel '%s': %s",
>>>>> diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
>>>>> index 96ec15016a314499acf65c6c47e0c4932aa99d01..5e8bd4dd73bbb27abccfa1fa577df52aed15b6a2 100644
>>>>> --- a/include/hw/loongarch/boot.h
>>>>> +++ b/include/hw/loongarch/boot.h
>>>>> @@ -8,6 +8,23 @@
>>>>> #ifndef HW_LOONGARCH_BOOT_H
>>>>> #define HW_LOONGARCH_BOOT_H
>>>>>
>>>>> +/* Linux Image Format */
>>>>> +#define LINUX_PE_MAGIC 0x818223cd
>>>>> +#define MZ_MAGIC 0x5a4d /* "MZ" */
>>>>> +
>>>>> +struct loongarch_linux_hdr {
>>>>> + uint32_t mz_magic;
>>>>> + uint32_t res0;
>>>>> + uint64_t kernel_entry;
>>>>> + uint64_t kernel_size;
>>>>> + uint64_t load_offset;
>>>>> + uint64_t res1;
>>>>> + uint64_t res2;
>>>>> + uint64_t res3;
>>>>> + uint32_t linux_pe_magic;
>>>>> + uint32_t pe_header_offset;
>>>>> +} QEMU_PACKED;
>>>>> +
>>>>> /* UEFI 2.10 */
>>>>> #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
>>>>> #define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
>>>>>
>>>>> ---
>>>>> base-commit: c69612063e1844b76ac01e3a781b979548c3585c
>>>>> change-id: 20241222-la-direct-kernel-boot-c598264710e7
>>>>>
>>>>> Best regards,
>>>>>
>>>
>
© 2016 - 2026 Red Hat, Inc.