From 4aaa34677317a2d9c574f368e8895a9a2971f002 Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Fri, 22 Mar 2013 21:01:28 +0100
Subject: [PATCH 224/482] 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 <phcoder@gmail.com>
+ Add ability to generate newc additions on runtime.
+
+2013-03-22 Vladimir Serbinenko <phcoder@gmail.com>
+
* 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 <grub/i386/relocator.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
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 <grub/video.h>
#include <grub/i386/floppy.h>
#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
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 <grub/elf.h>
#include <grub/i18n.h>
#include <grub/env.h>
+#include <grub/linux.h>
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 <grub/types.h>
+#include <grub/err.h>
+#include <grub/linux.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/mm.h>
+
+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 <grub/memory.h>
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
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 <grub/memory.h>
#include <grub/lib/cmdline.h>
#include <grub/cache.h>
+#include <grub/linux.h>
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 <grub/i18n.h>
#include <grub/memory.h>
#include <grub/lib/cmdline.h>
+#include <grub/linux.h>
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 <grub/file.h>
+
+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