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; grub_ssize_t cursize = 0; for (i = 0; i < initrd_ctx->nfiles; i++) { grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ptr += ALIGN_UP_OVERHEAD (cursize, 4); 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; } if (newc) ptr = make_header (ptr, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0); free_dir (root); root = 0; return GRUB_ERR_NONE; }
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 grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t *files = 0; int i, nfiles = 0; grub_size_t size = 0; grub_uint8_t *ptr; if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (!loaded) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } files = grub_zalloc (argc * sizeof (files[0])); if (!files) 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); } initrd_mem = grub_efi_allocate_pages_max (0x3fffffff, BYTES_TO_PAGES(size)); if (!initrd_mem) { grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("can't allocate initrd")); goto fail; } params->ramdisk_size = size; params->ramdisk_image = (grub_uint32_t)(grub_uint64_t) initrd_mem; 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; } grub_tpm_measure (ptr, cursize, GRUB_INITRD_PCR); ptr += cursize; grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ptr += ALIGN_UP_OVERHEAD (cursize, 4); } params->ramdisk_size = size; fail: for (i = 0; i < nfiles; i++) grub_file_close (files[i]); grub_free (files); if (initrd_mem && grub_errno) grub_efi_free_pages((grub_efi_physical_address_t)initrd_mem, BYTES_TO_PAGES(size)); return grub_errno; }