2014-06-18 06:41:22

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 1/2] efilinux: Allocate boot_params before parsing initrd

We need to allocate boot_params early and clear it before copy
setup_header to it.

So kernel will not call sanitize_boot_params() to overwrite new
added parameter like ext_ramdisk_image, ext_ramdisk_size...

We should modify boot_params later instead of touch temp buf too early.

Signed-off-by: Yinghai Lu <[email protected]>

---
loaders/bzimage/bzimage.c | 65 ++++++++++++++++++++++++----------------------
1 file changed, 34 insertions(+), 31 deletions(-)

Index: efilinux/loaders/bzimage/bzimage.c
===================================================================
--- efilinux.orig/loaders/bzimage/bzimage.c
+++ efilinux/loaders/bzimage/bzimage.c
@@ -50,21 +50,22 @@ struct initrd {
struct file *file;
};

-static void parse_initrd(EFI_LOADED_IMAGE *image, struct boot_params *buf, char *cmdline)
+static void parse_initrd(EFI_LOADED_IMAGE *image,
+ struct boot_params *boot_params, char *cmdline)
{
EFI_PHYSICAL_ADDRESS addr;
struct initrd *initrds;
int nr_initrds;
EFI_STATUS err;
- UINT64 size;
+ UINT64 size = 0;
char *initrd;
int i, j;

/*
* Has there been an initrd specified on the cmdline?
*/
- buf->hdr.ramdisk_start = 0;
- buf->hdr.ramdisk_len = 0;
+ boot_params->hdr.ramdisk_start = 0;
+ boot_params->hdr.ramdisk_len = 0;

initrd = cmdline;
for (nr_initrds = 0; *initrd; nr_initrds++) {
@@ -96,6 +97,7 @@ static void parse_initrd(EFI_LOADED_IMAG
struct initrd *rd = &initrds[i];
struct file *rdfile;
char *o, *p;
+ UINT64 sz;

initrd = strstr(initrd, "initrd=");
if (!initrd)
@@ -116,26 +118,26 @@ static void parse_initrd(EFI_LOADED_IMAG
if (err != EFI_SUCCESS)
goto close_handles;

- file_size(rdfile, &size);
+ file_size(rdfile, &sz);

- rd->size = size;
+ rd->size = sz;
rd->file = rdfile;

- buf->hdr.ramdisk_len += size;
+ size += sz;
}

- size = buf->hdr.ramdisk_len;
err = emalloc(size, 0x1000, &addr);
if (err != EFI_SUCCESS)
goto close_handles;

- if ((UINTN)addr > buf->hdr.ramdisk_max) {
+ if ((UINTN)addr > boot_params->hdr.ramdisk_max) {
Print(L"ramdisk address is too high!\n");
efree(addr, size);
goto close_handles;
}

- buf->hdr.ramdisk_start = (UINT32)(UINTN)addr;
+ boot_params->hdr.ramdisk_start = (UINT32)(UINTN)addr;
+ boot_params->hdr.ramdisk_len = (UINT32)size;

for (j = 0; j < nr_initrds; j++) {
struct initrd *rd = &initrds[j];
@@ -268,9 +270,6 @@ load_kernel(EFI_HANDLE image, CHAR16 *na
init_size = size * 3;
}

- /* Don't need an allocated ID, we're a prototype */
- buf->hdr.loader_id = 0x1;
-
/*
* The kernel expects cmdline to be allocated pretty low,
* Documentation/x86/boot.txt says,
@@ -287,11 +286,26 @@ load_kernel(EFI_HANDLE image, CHAR16 *na
cmdline = (char *)(UINTN)addr;
memcpy(cmdline, _cmdline, strlen(_cmdline) + 1);

- parse_initrd(info, buf, cmdline);
+ addr = 0x3fffffff;
+ err = allocate_pages(AllocateMaxAddress, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(16384), &addr);
+ if (err != EFI_SUCCESS)
+ goto out;
+
+ boot_params = (struct boot_params *)(UINTN)addr;

- buf->hdr.cmd_line_ptr = (UINT32)(UINTN)cmdline;
+ memset((void *)boot_params, 0x0, 16384);
+
+ /* Copy setup_header to boot_params */
+ memcpy((char *)&boot_params->hdr, (char *)&buf->hdr,
+ sizeof(struct setup_header));

- memset((char *)&buf->screen_info, 0x0, sizeof(buf->screen_info));
+ /* Don't need an allocated ID, we're a prototype */
+ boot_params->hdr.loader_id = 0x1;
+
+ boot_params->hdr.cmd_line_ptr = (UINT32)(UINTN)cmdline;
+
+ parse_initrd(info, boot_params, cmdline);

addr = pref_address;
err = allocate_pages(AllocateAddress, EfiLoaderData,
@@ -301,7 +315,8 @@ load_kernel(EFI_HANDLE image, CHAR16 *na
* We failed to allocate the preferred address, so
* just allocate some memory and hope for the best.
*/
- err = emalloc(init_size, buf->hdr.kernel_alignment, &addr);
+ err = emalloc(init_size, boot_params->hdr.kernel_alignment,
+ &addr);
if (err != EFI_SUCCESS)
goto out;
}
@@ -315,26 +330,14 @@ load_kernel(EFI_HANDLE image, CHAR16 *na
if (err != EFI_SUCCESS)
goto out;

- addr = 0x3fffffff;
- err = allocate_pages(AllocateMaxAddress, EfiLoaderData,
- EFI_SIZE_TO_PAGES(16384), &addr);
- if (err != EFI_SUCCESS)
- goto out;
-
- boot_params = (struct boot_params *)(UINTN)addr;
-
- memset((void *)boot_params, 0x0, 16384);
-
- /* Copy first two sectors to boot_params */
- memcpy((char *)boot_params, (char *)buf, 2 * 512);
boot_params->hdr.code32_start = (UINT32)((UINT64)kernel_start);

/*
* Use the kernel's EFI boot stub by invoking the handover
* protocol.
*/
- if (buf->hdr.version >= 0x20b) {
- handover_jump(buf->hdr.version, image,
+ if (boot_params->hdr.version >= 0x20b) {
+ handover_jump(boot_params->hdr.version, image,
boot_params, kernel_start);
goto out;
}


2014-06-18 06:41:32

by Yinghai Lu

[permalink] [raw]
Subject: [PATCH 2/2] efilinux: set ext_ramdisk_* for huge initrd

We could load it high if it is more than 2G when kernel support
LOAD_ABOVE_4G.

Signed-off-by: Yinghai Lu <[email protected]>

---
loaders/bzimage/bzimage.c | 9 ++++++++-
loaders/bzimage/bzimage.h | 8 ++++++--
2 files changed, 14 insertions(+), 3 deletions(-)

Index: efilinux/loaders/bzimage/bzimage.c
===================================================================
--- efilinux.orig/loaders/bzimage/bzimage.c
+++ efilinux/loaders/bzimage/bzimage.c
@@ -130,7 +130,9 @@ static void parse_initrd(EFI_LOADED_IMAG
if (err != EFI_SUCCESS)
goto close_handles;

- if ((UINTN)addr > boot_params->hdr.ramdisk_max) {
+ if ((boot_params->hdr.version < 0x20c ||
+ !(boot_params->hdr.xloadflags & (1<<1))) &&
+ (UINTN)addr > boot_params->hdr.ramdisk_max) {
Print(L"ramdisk address is too high!\n");
efree(addr, size);
goto close_handles;
@@ -138,6 +140,11 @@ static void parse_initrd(EFI_LOADED_IMAG

boot_params->hdr.ramdisk_start = (UINT32)(UINTN)addr;
boot_params->hdr.ramdisk_len = (UINT32)size;
+ if (boot_params->hdr.version >= 0x20c &&
+ (boot_params->hdr.xloadflags & (1<<1))) {
+ boot_params->ext_ramdisk_image = (UINT64)(UINTN)addr >> 32;
+ boot_params->ext_ramdisk_size = size >> 32;
+ }

for (j = 0; j < nr_initrds; j++) {
struct initrd *rd = &initrds[j];
Index: efilinux/loaders/bzimage/bzimage.h
===================================================================
--- efilinux.orig/loaders/bzimage/bzimage.h
+++ efilinux/loaders/bzimage/bzimage.h
@@ -69,7 +69,8 @@ struct setup_header {
UINT32 ramdisk_max; /* Highest legal initrd address */
UINT32 kernel_alignment; /* Physical addr alignment required for kernel */
UINT8 relocatable_kernel; /* Whether kernel is relocatable or not */
- UINT8 _pad2[3];
+ UINT8 min_alignment;
+ UINT16 xloadflags;
UINT32 cmdline_size;
UINT32 hardware_subarch;
UINT64 hardware_subarch_data;
@@ -148,7 +149,10 @@ struct boot_params {
UINT8 hd1_info[16];
UINT8 sys_desc_table[0x10];
UINT8 olpc_ofw_header[0x10];
- UINT8 _pad4[128];
+ UINT32 ext_ramdisk_image;
+ UINT32 ext_ramdisk_size;
+ UINT32 ext_cmd_line_ptr;
+ UINT8 _pad4[116];
UINT8 edid_info[0x80];
struct efi_info efi_info;
UINT32 alt_mem_k;

2014-06-25 20:45:58

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 1/2] efilinux: Allocate boot_params before parsing initrd

On Tue, 17 Jun, at 11:41:08PM, Yinghai Lu wrote:
> We need to allocate boot_params early and clear it before copy
> setup_header to it.
>
> So kernel will not call sanitize_boot_params() to overwrite new
> added parameter like ext_ramdisk_image, ext_ramdisk_size...
>
> We should modify boot_params later instead of touch temp buf too early.
>
> Signed-off-by: Yinghai Lu <[email protected]>
>
> ---
> loaders/bzimage/bzimage.c | 65 ++++++++++++++++++++++++----------------------
> 1 file changed, 34 insertions(+), 31 deletions(-)

Applied, thanks!

--
Matt Fleming, Intel Open Source Technology Center

2014-06-25 20:47:05

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 2/2] efilinux: set ext_ramdisk_* for huge initrd

On Tue, 17 Jun, at 11:41:09PM, Yinghai Lu wrote:
> We could load it high if it is more than 2G when kernel support
> LOAD_ABOVE_4G.
>
> Signed-off-by: Yinghai Lu <[email protected]>
>
> ---
> loaders/bzimage/bzimage.c | 9 ++++++++-
> loaders/bzimage/bzimage.h | 8 ++++++--
> 2 files changed, 14 insertions(+), 3 deletions(-)
>
> Index: efilinux/loaders/bzimage/bzimage.c
> ===================================================================
> --- efilinux.orig/loaders/bzimage/bzimage.c
> +++ efilinux/loaders/bzimage/bzimage.c
> @@ -130,7 +130,9 @@ static void parse_initrd(EFI_LOADED_IMAG
> if (err != EFI_SUCCESS)
> goto close_handles;
>
> - if ((UINTN)addr > boot_params->hdr.ramdisk_max) {
> + if ((boot_params->hdr.version < 0x20c ||
> + !(boot_params->hdr.xloadflags & (1<<1))) &&
> + (UINTN)addr > boot_params->hdr.ramdisk_max) {

Could you please add a #define for the xloadflags bit?

--
Matt Fleming, Intel Open Source Technology Center