static grub_err_t grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; grub_ssize_t size; void *module = NULL; grub_addr_t target; grub_err_t err; int nounzip = 0; grub_uint64_t lowest_addr = 0; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (grub_strcmp (argv[0], "--nounzip") == 0) { argv++; argc--; nounzip = 1; } if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (!grub_multiboot_relocator) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); if (nounzip) grub_file_filter_disable_compression (); file = grub_file_open (argv[0]); if (! file) return grub_errno; #ifndef GRUB_USE_MULTIBOOT2 lowest_addr = 0x100000; if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL) lowest_addr = ALIGN_UP (highest_load + 1048576, 4096); #endif size = grub_file_size (file); if (size) { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, lowest_addr, (0xffffffff - size) + 1, size, MULTIBOOT_MOD_ALIGN, GRUB_RELOCATOR_PREFERENCE_NONE, 1); if (err) { grub_file_close (file); return err; } module = get_virtual_current_address (ch); target = get_physical_target_address (ch); } else { module = 0; target = 0; } err = grub_multiboot_add_module (target, size, argc - 1, argv + 1); if (err) { grub_file_close (file); return err; } if (size && grub_file_read (file, module, size) != size) { grub_file_close (file); if (!grub_errno) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), argv[0]); return grub_errno; } grub_file_close (file); return GRUB_ERR_NONE; }
/* Read block header from file, after successful exit file points to * beginning of block data. */ static int read_block_header (struct grub_lzopio *lzopio) { lzopio->saved_off += lzopio->block.usize; /* Free cached block data if any. */ grub_free (lzopio->block.udata); grub_free (lzopio->block.cdata); lzopio->block.udata = NULL; lzopio->block.cdata = NULL; if (grub_file_read (lzopio->file, &lzopio->block.usize, sizeof (lzopio->block.usize)) != sizeof (lzopio->block.usize)) return -1; lzopio->block.usize = grub_be_to_cpu32 (lzopio->block.usize); /* Last block has uncompressed data size == 0 and no other fields. */ if (lzopio->block.usize == 0) { if (grub_file_tell (lzopio->file) == grub_file_size (lzopio->file)) return 0; else return -1; } /* Read compressed data block size. */ if (grub_file_read (lzopio->file, &lzopio->block.csize, sizeof (lzopio->block.csize)) != sizeof (lzopio->block.csize)) return -1; lzopio->block.csize = grub_be_to_cpu32 (lzopio->block.csize); /* Corrupted. */ if (lzopio->block.csize > lzopio->block.usize) return -1; /* Read checksum of uncompressed data. */ if (lzopio->has_ucheck) { if (grub_file_read (lzopio->file, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != sizeof (lzopio->block.ucheck)) return -1; lzopio->block.ucheck = lzopio->block.ucheck; } /* Read checksum of compressed data. */ if (lzopio->has_ccheck) { /* Incompressible data block. */ if (lzopio->block.csize == lzopio->block.usize) { lzopio->block.ccheck = lzopio->block.ucheck; } else { if (grub_file_read (lzopio->file, &lzopio->block.ccheck, sizeof (lzopio->block.ccheck)) != sizeof (lzopio->block.ccheck)) return -1; lzopio->block.ccheck = lzopio->block.ccheck; } } return 0; }
static grub_err_t grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; grub_err_t err; void *bs, *ntldr; grub_size_t ntldrsize; grub_device_t dev; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); rel = grub_relocator_new (); if (!rel) goto fail; file = grub_file_open (argv[0]); if (! file) goto fail; { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, GRUB_DISK_SECTOR_SIZE); if (err) goto fail; bs = get_virtual_current_address (ch); } edx = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk) { err = grub_disk_read (dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, bs); if (err) { grub_device_close (dev); goto fail; } grub_chainloader_patch_bpb (bs, dev, edx); } if (dev) grub_device_close (dev); ntldrsize = grub_file_size (file); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_NTLDR_SEGMENT << 4, ntldrsize); if (err) goto fail; ntldr = get_virtual_current_address (ch); } if (grub_file_read (file, ntldr, ntldrsize) != (grub_ssize_t) ntldrsize) goto fail; grub_loader_set (grub_ntldr_boot, grub_ntldr_unload, 1); /* Begin TCG Extension */ if (grub_TPM_isAvailable()) grub_TPM_measureFile( argv[0], TPM_LOADED_FILES_PCR ); /* End TCG Extension */ return GRUB_ERR_NONE; fail: if (file) grub_file_close (file); grub_ntldr_unload (); return grub_errno; }
void grub_module2 (int argc, char *argv[]) { grub_file_t file; grub_addr_t modaddr = 0; grub_ssize_t modsize = 0; grub_err_t err; if (argc == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); return; } if (argc == 1) { grub_error (GRUB_ERR_BAD_ARGUMENT, "No module type specified"); return; } if (entry == 0) { grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the multiboot kernel first"); return; } /* Load module data. */ file = grub_gzfile_open (argv[0], 1); if (! file) goto out; modsize = grub_file_size (file); err = grub_mb2_arch_module_alloc (modsize, &modaddr); if (err) goto out; grub_dprintf ("loader", "Loading module at 0x%x - 0x%x\n", modaddr, modaddr + modsize); if (grub_file_read (file, (char *) modaddr, modsize) != modsize) { grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); goto out; } /* Create the module tag. */ err = grub_mb2_tag_module_create (modaddr, modsize, argv[1], MULTIBOOT2_TAG_MODULE, argc-2, &argv[2]); if (err) goto out; out: grub_error_push (); if (file) grub_file_close (file); if (modaddr) grub_mb2_arch_module_free (modaddr, modsize); grub_error_pop (); }
static int test_gzip_header (grub_file_t file) { struct { grub_uint16_t magic; grub_uint8_t method; grub_uint8_t flags; grub_uint32_t timestamp; grub_uint8_t extra_flags; grub_uint8_t os_type; } hdr; grub_uint16_t extra_len; grub_uint32_t orig_len; grub_gzio_t gzio = file->data; if (grub_file_tell (gzio->file) != 0) grub_file_seek (gzio->file, 0); /* * This checks if the file is gzipped. If a problem occurs here * (other than a real error with the disk) then we don't think it * is a compressed file, and simply mark it as such. */ if (grub_file_read (gzio->file, &hdr, 10) != 10 || ((hdr.magic != GZIP_MAGIC) && (hdr.magic != OLD_GZIP_MAGIC))) { grub_error (GRUB_ERR_BAD_FILE_TYPE, "no gzip magic found"); return 0; } /* * This does consistency checking on the header data. If a * problem occurs from here on, then we have corrupt or otherwise * bad data, and the error should be reported to the user. */ if (hdr.method != DEFLATED || (hdr.flags & UNSUPPORTED_FLAGS) || ((hdr.flags & EXTRA_FIELD) && (grub_file_read (gzio->file, &extra_len, 2) != 2 || eat_field (gzio->file, grub_le_to_cpu16 (extra_len)))) || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1))) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); return 0; } gzio->data_offset = grub_file_tell (gzio->file); /* FIXME: don't do this on not easily seekable files. */ { grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); if (grub_file_read (gzio->file, &orig_len, 4) != 4) { grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format"); return 0; } /* FIXME: this does not handle files whose original size is over 4GB. But how can we know the real original size? */ file->size = grub_le_to_cpu32 (orig_len); } initialize_tables (gzio); return 1; }
grub_macho_t grub_macho_file (grub_file_t file, const char *filename, int is_64bit) { grub_macho_t macho; union grub_macho_filestart filestart; macho = grub_malloc (sizeof (*macho)); if (! macho) return 0; macho->file = file; macho->offset32 = -1; macho->offset64 = -1; macho->end32 = -1; macho->end64 = -1; macho->cmds32 = 0; macho->cmds64 = 0; macho->uncompressed32 = 0; macho->uncompressed64 = 0; macho->compressed32 = 0; macho->compressed64 = 0; if (grub_file_seek (macho->file, 0) == (grub_off_t) -1) goto fail; if (grub_file_read (macho->file, &filestart, sizeof (filestart)) != sizeof (filestart)) { if (!grub_errno) grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename); goto fail; } /* Is it a fat file? */ if (filestart.fat.magic == grub_cpu_to_be32_compile_time (GRUB_MACHO_FAT_MAGIC)) { struct grub_macho_fat_arch *archs; int i, narchs; /* Load architecture description. */ narchs = grub_be_to_cpu32 (filestart.fat.nfat_arch); if (grub_file_seek (macho->file, sizeof (struct grub_macho_fat_header)) == (grub_off_t) -1) goto fail; archs = grub_malloc (sizeof (struct grub_macho_fat_arch) * narchs); if (!archs) goto fail; if (grub_file_read (macho->file, archs, sizeof (struct grub_macho_fat_arch) * narchs) != (grub_ssize_t) sizeof(struct grub_macho_fat_arch) * narchs) { grub_free (archs); if (!grub_errno) grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename); goto fail; } for (i = 0; i < narchs; i++) { if ((archs[i].cputype == grub_cpu_to_be32_compile_time (GRUB_MACHO_CPUTYPE_IA32)) && !is_64bit) { macho->offset32 = grub_be_to_cpu32 (archs[i].offset); macho->end32 = grub_be_to_cpu32 (archs[i].offset) + grub_be_to_cpu32 (archs[i].size); } if ((archs[i].cputype == grub_cpu_to_be32_compile_time (GRUB_MACHO_CPUTYPE_AMD64)) && is_64bit) { macho->offset64 = grub_be_to_cpu32 (archs[i].offset); macho->end64 = grub_be_to_cpu32 (archs[i].offset) + grub_be_to_cpu32 (archs[i].size); } } grub_free (archs); } /* Is it a thin 32-bit file? */ if (filestart.thin32.magic == GRUB_MACHO_MAGIC32 && !is_64bit) { macho->offset32 = 0; macho->end32 = grub_file_size (file); } /* Is it a thin 64-bit file? */ if (filestart.thin64.magic == GRUB_MACHO_MAGIC64 && is_64bit) { macho->offset64 = 0; macho->end64 = grub_file_size (file); } if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC, sizeof (filestart.lzss.magic)) == 0 && !is_64bit) { macho->offset32 = 0; macho->end32 = grub_file_size (file); } /* Is it a thin 64-bit file? */ if (grub_memcmp (filestart.lzss.magic, GRUB_MACHO_LZSS_MAGIC, sizeof (filestart.lzss.magic)) == 0 && is_64bit) { macho->offset64 = 0; macho->end64 = grub_file_size (file); } grub_macho_parse32 (macho, filename); grub_macho_parse64 (macho, filename); if (macho->offset32 == -1 && !is_64bit) { grub_error (GRUB_ERR_BAD_OS, "Mach-O doesn't contain suitable 32-bit architecture"); goto fail; } if (macho->offset64 == -1 && is_64bit) { grub_error (GRUB_ERR_BAD_OS, "Mach-O doesn't contain suitable 64-bit architecture"); goto fail; } return macho; fail: macho->file = 0; grub_macho_close (macho); return 0; }