From 4aaa34677317a2d9c574f368e8895a9a2971f002 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Mar 2013 21:01:28 +0100 Subject: [PATCH 224/471] Add ability to generate newc additions on runtime. --- ChangeLog | 4 + grub-core/Makefile.core.def | 2 + grub-core/loader/i386/linux.c | 40 +--- grub-core/loader/i386/pc/linux.c | 40 +--- grub-core/loader/ia64/efi/linux.c | 42 +---- grub-core/loader/linux.c | 294 ++++++++++++++++++++++++++++++ grub-core/loader/mips/linux.c | 40 +--- grub-core/loader/powerpc/ieee1275/linux.c | 41 +---- grub-core/loader/sparc64/ieee1275/linux.c | 40 +--- include/grub/linux.h | 24 +++ 10 files changed, 366 insertions(+), 201 deletions(-) create mode 100644 grub-core/loader/linux.c create mode 100644 include/grub/linux.h diff --git a/ChangeLog b/ChangeLog index 4a5b683..5582e13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2013-03-22 Vladimir Serbinenko + Add ability to generate newc additions on runtime. + +2013-03-22 Vladimir Serbinenko + * grub-core/commands/i386/coreboot/cbls.c: Fix typos and wrong description. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index d851bc3..a614b22 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1406,6 +1406,7 @@ module = { module = { name = linux16; common = loader/i386/pc/linux.c; + common = loader/linux.c; common = lib/cmdline.c; enable = x86; }; @@ -1454,6 +1455,7 @@ module = { powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; ia64_efi = loader/ia64/efi/linux.c; + common = loader/linux.c; common = lib/cmdline.c; enable = noemu; }; diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 92cabfb..bdfe19a 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -34,6 +34,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -1055,14 +1056,11 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; grub_size_t size = 0; grub_addr_t addr_min, addr_max; grub_addr_t addr; grub_err_t err; - int i; - int nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) { @@ -1076,19 +1074,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - size += ALIGN_UP (grub_file_size (files[i]), 4); - } + size = grub_get_initrd_size (&initrd_ctx); initrd_pages = (page_align (size) >> 12); @@ -1138,21 +1127,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_mem_target = get_physical_target_address (ch); } - ptr = initrd_mem; - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) + goto fail; grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n", (unsigned) addr, (unsigned) size); @@ -1162,9 +1138,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), linux_params.root_dev = 0x0100; /* XXX */ fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 3ce21bc..672c013 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -34,6 +34,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -381,15 +382,13 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; grub_size_t size = 0; grub_addr_t addr_max, addr_min; struct linux_kernel_header *lh; grub_uint8_t *initrd_chunk; grub_addr_t initrd_addr; grub_err_t err; - int i, nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) { @@ -437,19 +436,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = GRUB_LINUX_BZIMAGE_ADDR + grub_linux16_prot_size; - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - size += ALIGN_UP (grub_file_size (files[i]), 4); - } + size = grub_get_initrd_size (&initrd_ctx); { grub_relocator_chunk_t ch; @@ -463,30 +453,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_addr = get_physical_target_address (ch); } - ptr = initrd_chunk; - - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, initrd_chunk)) + goto fail; lh->ramdisk_image = initrd_addr; lh->ramdisk_size = size; fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 17843fd..87ac49f 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -32,6 +32,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -567,10 +568,7 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; - int i; - int nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) { @@ -584,22 +582,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - initrd_size = 0; + initrd_size = grub_get_initrd_size (&initrd_ctx); grub_dprintf ("linux", "Loading initrd\n"); - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - initrd_size += ALIGN_UP (grub_file_size (files[i]), 4); - grub_dprintf ("linux", "File %d: %s\n", i, argv[i]); - } initrd_pages = (page_align (initrd_size) >> 12); initrd_mem = grub_efi_allocate_pages (0, initrd_pages); @@ -612,25 +599,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("linux", "[addr=0x%lx, size=0x%lx]\n", (grub_uint64_t) initrd_mem, initrd_size); - ptr = initrd_mem; - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, initrd_mem)) + goto fail; fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c new file mode 100644 index 0000000..cbe3c53 --- /dev/null +++ b/grub-core/loader/linux.c @@ -0,0 +1,294 @@ +#include +#include +#include +#include +#include +#include + +struct newc_head +{ + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; +} __attribute__ ((packed)); + +struct grub_linux_initrd_component +{ + grub_file_t file; + char *newc_name; + grub_off_t size; +}; + +struct dir +{ + char *name; + struct dir *next; + struct dir *child; +}; + +static char +hex (grub_uint8_t val) +{ + if (val < 10) + return '0' + val; + return 'a' + val - 10; +} + +static void +set_field (char *var, grub_uint32_t val) +{ + int i; + char *ptr = var; + for (i = 28; i >= 0; i -= 4) + *ptr++ = hex((val >> i) & 0xf); +} + +static grub_uint8_t * +make_header (grub_uint8_t *ptr, + const char *name, grub_size_t len, + grub_uint32_t mode, + grub_off_t fsize) +{ + struct newc_head *head = (struct newc_head *) ptr; + grub_uint8_t *optr; + grub_size_t oh = 0; + grub_memcpy (head->magic, "070701", 6); + set_field (head->ino, 0); + set_field (head->mode, mode); + set_field (head->uid, 0); + set_field (head->gid, 0); + set_field (head->nlink, 1); + set_field (head->mtime, 0); + set_field (head->filesize, fsize); + set_field (head->devmajor, 0); + set_field (head->devminor, 0); + set_field (head->rdevmajor, 0); + set_field (head->rdevminor, 0); + set_field (head->namesize, len); + set_field (head->check, 0); + optr = ptr; + ptr += sizeof (struct newc_head); + grub_memcpy (ptr, name, len); + ptr += len; + oh = ALIGN_UP_OVERHEAD (ptr - optr, 4); + grub_memset (ptr, 0, oh); + ptr += oh; + return ptr; +} + +static void +free_dir (struct dir *root) +{ + if (!root) + return; + free_dir (root->next); + free_dir (root->child); + grub_free (root->name); + grub_free (root); +} + +static grub_size_t +insert_dir (const char *name, struct dir **root, + grub_uint8_t *ptr) +{ + struct dir *cur, **head = root; + const char *cb, *ce = name; + grub_size_t size = 0; + while (1) + { + for (cb = ce; *cb == '/'; cb++); + for (ce = cb; *ce && *ce != '/'; ce++); + if (!*ce) + break; + + for (cur = *root; cur; cur = cur->next) + if (grub_memcmp (cur->name, cb, ce - cb) + && cur->name[ce - cb] == 0) + break; + if (!cur) + { + struct dir *n; + n = grub_zalloc (sizeof (*n)); + if (!n) + return 0; + n->next = *head; + n->name = grub_strndup (cb, ce - cb); + if (ptr) + { + grub_printf ("Creating directory %s, %s\n", name, ce); + ptr = make_header (ptr, name, ce - name, + 040777, 0); + } + size += ALIGN_UP ((ce - (char *) name) + + sizeof (struct newc_head), 4); + *head = n; + cur = n; + } + root = &cur->next; + } + return size; +} + +grub_err_t +grub_initrd_init (int argc, char *argv[], + struct grub_linux_initrd_context *initrd_ctx) +{ + int i; + int newc = 0; + struct dir *root = 0; + + initrd_ctx->nfiles = 0; + initrd_ctx->components = 0; + + initrd_ctx->components = grub_zalloc (argc + * sizeof (initrd_ctx->components[0])); + if (!initrd_ctx->components) + return grub_errno; + + initrd_ctx->size = 0; + + for (i = 0; i < argc; i++) + { + const char *fname = argv[i]; + if (grub_memcmp (argv[i], "newc:", 5) == 0) + { + const char *ptr, *eptr; + ptr = argv[i] + 5; + while (*ptr == '/') + ptr++; + eptr = grub_strchr (ptr, ':'); + if (eptr) + { + grub_file_filter_disable_compression (); + initrd_ctx->components[i].newc_name = grub_strndup (ptr, eptr - ptr); + if (!initrd_ctx->components[i].newc_name) + { + grub_initrd_close (initrd_ctx); + return grub_errno; + } + initrd_ctx->size + += ALIGN_UP (sizeof (struct newc_head) + + grub_strlen (initrd_ctx->components[i].newc_name), + 4); + initrd_ctx->size += insert_dir (initrd_ctx->components[i].newc_name, + &root, 0); + newc = 1; + fname = eptr + 1; + } + } + else if (newc) + { + initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head) + + sizeof ("TRAILER!!!") - 1, 4); + free_dir (root); + root = 0; + newc = 0; + } + grub_file_filter_disable_compression (); + initrd_ctx->components[i].file = grub_file_open (fname); + if (!initrd_ctx->components[i].file) + { + grub_initrd_close (initrd_ctx); + return grub_errno; + } + initrd_ctx->nfiles++; + initrd_ctx->components[i].size + = grub_file_size (initrd_ctx->components[i].file); + initrd_ctx->size += ALIGN_UP (initrd_ctx->components[i].size, 4); + } + + if (newc) + { + initrd_ctx->size += ALIGN_UP (sizeof (struct newc_head) + + sizeof ("TRAILER!!!") - 1, 4); + free_dir (root); + root = 0; + } + + return GRUB_ERR_NONE; +} + +grub_size_t +grub_get_initrd_size (struct grub_linux_initrd_context *initrd_ctx) +{ + return initrd_ctx->size; +} + +void +grub_initrd_close (struct grub_linux_initrd_context *initrd_ctx) +{ + int i; + if (!initrd_ctx->components) + return; + for (i = 0; i < initrd_ctx->nfiles; i++) + { + grub_free (initrd_ctx->components[i].newc_name); + grub_file_close (initrd_ctx->components[i].file); + } + grub_free (initrd_ctx->components); + initrd_ctx->components = 0; +} + +grub_err_t +grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + char *argv[], void *target) +{ + grub_uint8_t *ptr = target; + int i; + int newc = 0; + struct dir *root = 0; + + for (i = 0; i < initrd_ctx->nfiles; i++) + { + grub_ssize_t cursize; + + if (initrd_ctx->components[i].newc_name) + { + ptr += insert_dir (initrd_ctx->components[i].newc_name, + &root, ptr); + ptr = make_header (ptr, initrd_ctx->components[i].newc_name, + grub_strlen (initrd_ctx->components[i].newc_name), + 0100777, + initrd_ctx->components[i].size); + newc = 1; + } + else if (newc) + { + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, + 0, 0); + free_dir (root); + root = 0; + newc = 0; + } + + cursize = initrd_ctx->components[i].size; + if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize) + != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + grub_initrd_close (initrd_ctx); + return grub_errno; + } + ptr += cursize; + grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); + ptr += ALIGN_UP_OVERHEAD (cursize, 4); + } + if (newc) + ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); + free_dir (root); + root = 0; + return GRUB_ERR_NONE; +} diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 653f8a2..ef64a5b 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -410,14 +411,11 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; grub_size_t size = 0; void *initrd_src; grub_addr_t initrd_dest; grub_err_t err; - int i; - int nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); @@ -428,19 +426,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), if (initrd_loaded) return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - size += ALIGN_UP (grub_file_size (files[i]), 4); - } + size = grub_get_initrd_size (&initrd_ctx); { grub_relocator_chunk_t ch; @@ -458,21 +447,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_dest = get_physical_target_address (ch) | 0x80000000; } - ptr = initrd_src; - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, initrd_src)) + goto fail; #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS { @@ -504,9 +480,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_loaded = 1; fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c index 9055399..cff4fd1 100644 --- a/grub-core/loader/powerpc/ieee1275/linux.c +++ b/grub-core/loader/powerpc/ieee1275/linux.c @@ -29,6 +29,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -315,13 +316,10 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; grub_size_t size = 0; grub_addr_t first_addr; grub_addr_t addr; - int i; - int nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) { @@ -335,19 +333,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - size += ALIGN_UP (grub_file_size (files[i]), 4); - } + size = grub_get_initrd_size (&initrd_ctx); first_addr = linux_addr + linux_size; @@ -359,30 +348,14 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size); - ptr = (void *) addr; - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - grub_ieee1275_release (addr, size); - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, (void *) addr)) + goto fail; initrd_addr = addr; initrd_size = size; fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index d203377..577ecff 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -368,14 +369,11 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t *files = 0; grub_size_t size = 0; grub_addr_t paddr; grub_addr_t addr; int ret; - int i; - int nfiles = 0; - grub_uint8_t *ptr; + struct grub_linux_initrd_context initrd_ctx; if (argc == 0) { @@ -389,19 +387,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - files = grub_zalloc (argc * sizeof (files[0])); - if (!files) + if (grub_initrd_init (argc, argv, &initrd_ctx)) goto fail; - for (i = 0; i < argc; i++) - { - grub_file_filter_disable_compression (); - files[i] = grub_file_open (argv[i]); - if (! files[i]) - goto fail; - nfiles++; - size += ALIGN_UP(grub_file_size (files[i]), 4); - } + size = grub_get_initrd_size (&initrd_ctx); addr = 0x60000000; @@ -423,30 +412,15 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("loader", "Loading initrd at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", addr, paddr, size); - ptr = (void *) addr; - for (i = 0; i < nfiles; i++) - { - grub_ssize_t cursize = grub_file_size (files[i]); - if (grub_file_read (files[i], ptr, cursize) != cursize) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - argv[i]); - goto fail; - } - ptr += cursize; - grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); - ptr += ALIGN_UP_OVERHEAD (cursize, 4); - } + if (grub_initrd_load (&initrd_ctx, argv, (void *) addr)) + goto fail; initrd_addr = addr; initrd_paddr = paddr; initrd_size = size; fail: - for (i = 0; i < nfiles; i++) - grub_file_close (files[i]); - grub_free (files); + grub_initrd_close (&initrd_ctx); return grub_errno; } diff --git a/include/grub/linux.h b/include/grub/linux.h new file mode 100644 index 0000000..594a3f3 --- /dev/null +++ b/include/grub/linux.h @@ -0,0 +1,24 @@ +#include + +struct grub_linux_initrd_component; + +struct grub_linux_initrd_context +{ + int nfiles; + struct grub_linux_initrd_component *components; + grub_size_t size; +}; + +grub_err_t +grub_initrd_init (int argc, char *argv[], + struct grub_linux_initrd_context *ctx); + +grub_size_t +grub_get_initrd_size (struct grub_linux_initrd_context *ctx); + +void +grub_initrd_close (struct grub_linux_initrd_context *initrd_ctx); + +grub_err_t +grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, + char *argv[], void *target); -- 1.8.2.1