char * grub_gpt_guid_to_str (grub_gpt_guid_t *guid) { return grub_xasprintf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", grub_le_to_cpu32 (guid->data1), grub_le_to_cpu16 (guid->data2), grub_le_to_cpu16 (guid->data3), guid->data4[0], guid->data4[1], guid->data4[2], guid->data4[3], guid->data4[4], guid->data4[5], guid->data4[6], guid->data4[7]); }
static grub_err_t sun_pc_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { grub_partition_t p; struct grub_sun_pc_block block; int partnum; grub_err_t err; p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); if (! p) return grub_errno; p->partmap = &grub_sun_pc_partition_map; err = grub_disk_read (disk, 1, 0, sizeof (struct grub_sun_pc_block), &block); if (err) { grub_free (p); return err; } if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.magic)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun_pc partition table"); } if (! grub_sun_is_valid (&block)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); } /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ for (partnum = 0; partnum < GRUB_PARTMAP_SUN_PC_MAX_PARTS; partnum++) { struct grub_sun_pc_partition_descriptor *desc; if (block.partitions[partnum].id == 0 || block.partitions[partnum].id == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) continue; desc = &block.partitions[partnum]; p->start = grub_le_to_cpu32 (desc->start_sector); p->len = grub_le_to_cpu32 (desc->num_sectors); p->number = partnum; if (p->len) { if (hook (disk, p)) partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS; } } grub_free (p); return grub_errno; }
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))) 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))) 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) 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; }
static struct grub_ext2_data * grub_ext2_mount (grub_disk_t disk) { struct grub_ext2_data *data; data = grub_malloc (sizeof (struct grub_ext2_data)); if (!data) return 0; /* Read the superblock. */ grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock), &data->sblock); if (grub_errno) goto fail; /* Make sure this is an ext2 filesystem. */ if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC) { grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem"); goto fail; } /* Check the FS doesn't have feature bits enabled that we don't support. */ if (grub_le_to_cpu32 (data->sblock.feature_incompat) & ~(EXT2_DRIVER_SUPPORTED_INCOMPAT | EXT2_DRIVER_IGNORED_INCOMPAT)) { grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features"); goto fail; } data->disk = disk; data->diropen.data = data; data->diropen.ino = 2; data->diropen.inode_read = 1; data->inode = &data->diropen.inode; grub_ext2_read_inode (data, 2, data->inode); if (grub_errno) goto fail; return data; fail: if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem"); grub_free (data); return 0; }
grub_elf_t grub_xen_file (grub_file_t file) { grub_elf_t elf; struct linux_kernel_header lh; grub_file_t off_file; elf = grub_elf_file (file, file->name); if (elf) return elf; grub_errno = GRUB_ERR_NONE; if (grub_file_seek (file, 0) == (grub_off_t) -1) goto fail; if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) goto fail; if (lh.boot_flag != grub_cpu_to_le16 (0xaa55) || lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE) || grub_le_to_cpu16 (lh.version) < 0x0208) { grub_error (GRUB_ERR_BAD_OS, "version too old for xen boot"); return NULL; } if (lh.payload_length < 4) { grub_error (GRUB_ERR_BAD_OS, "payload too short"); return NULL; } grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n", (unsigned long long) (lh.setup_sects + 1) * 512 + lh.payload_offset, (unsigned long long) lh.payload_length - 4); off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512 + lh.payload_offset, lh.payload_length - 4); if (!off_file) goto fail; elf = grub_elf_file (off_file, file->name); if (elf) return elf; grub_file_offset_close (off_file); fail: grub_error (GRUB_ERR_BAD_OS, "not xen image"); return NULL; }
static struct grub_ext4_extent_header * grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf, struct grub_ext4_extent_header *ext_block, grub_uint32_t fileblock) { struct grub_ext4_extent_idx *index; while (1) { int i; grub_disk_addr_t block; index = (struct grub_ext4_extent_idx *) (ext_block + 1); if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC) return 0; if (ext_block->depth == 0) return ext_block; for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++) { if (fileblock < grub_le_to_cpu32(index[i].block)) break; } if (--i < 0) return 0; block = grub_le_to_cpu16 (index[i].leaf_hi); block = (block << 32) + grub_le_to_cpu32 (index[i].leaf); if (grub_disk_read (data->disk, block << LOG2_EXT2_BLOCK_SIZE (data), 0, EXT2_BLOCK_SIZE(data), buf)) return 0; ext_block = (struct grub_ext4_extent_header *) buf; } }
static inline unsigned long long read_number (const grub_uint16_t *arr, grub_size_t size) { long long ret = 0; #ifdef MODE_BIGENDIAN while (size--) ret = (ret << 16) | grub_be_to_cpu16 (*arr++); #else while (size--) ret = (ret << 16) | grub_le_to_cpu16 (*arr++); #endif return ret; }
void grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) { const Elf64_Ehdr *e = ehdr; grub_size_t cntt = 0, cntg = 0;; const Elf64_Shdr *s; Elf64_Word entsize; unsigned i; /* Find a symbol table. */ for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) break; if (i == grub_le_to_cpu16 (e->e_shnum)) return; entsize = s->sh_entsize; for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) { Elf64_Rela *rel, *max; for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); rel < max; rel++) switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) { case R_IA64_PCREL21B: cntt++; break; case R_IA64_LTOFF_FPTR22: case R_IA64_LTOFF22X: case R_IA64_LTOFF22: cntg++; break; } } *tramp = cntt; *got = cntg; }
grub_err_t grub_gpt_part_label (grub_device_t device, char **label) { struct grub_gpt_partentry entry; const grub_size_t name_len = ARRAY_SIZE (entry.name); const grub_size_t label_len = name_len * GRUB_MAX_UTF8_PER_UTF16 + 1; grub_size_t i; grub_uint8_t *end; if (grub_gpt_device_partentry (device, &entry)) return grub_errno; *label = grub_malloc (label_len); if (!*label) return grub_errno; for (i = 0; i < name_len; i++) entry.name[i] = grub_le_to_cpu16 (entry.name[i]); end = grub_utf16_to_utf8 ((grub_uint8_t *) *label, entry.name, name_len); *end = '\0'; return GRUB_ERR_NONE; }
static void grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) { grub_file_t file = 0; grub_uint16_t signature; grub_device_t dev; int drive = -1; void *part_addr = 0; grub_dl_ref (my_mod); file = grub_file_open (filename); if (! file) goto fail; /* Read the first block. */ if (grub_file_read (file, (void *) 0x7C00, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) { if (grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_BAD_OS, "too small"); goto fail; } /* Check the signature. */ signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2)); if (signature != grub_le_to_cpu16 (0xaa55) && ! (flags & GRUB_CHAINLOADER_FORCE)) { grub_error (GRUB_ERR_BAD_OS, "invalid signature"); goto fail; } grub_file_close (file); /* Obtain the partition table from the root device. */ drive = grub_get_root_biosnumber (); dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { grub_disk_t disk = dev->disk; if (disk) { grub_partition_t p = disk->partition; if (p && grub_strcmp (p->partmap->name, "msdos") == 0) { disk->partition = p->parent; grub_disk_read (disk, p->offset, 446, 64, (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR); part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR + (p->index << 4)); disk->partition = p; } } } if (dev) grub_device_close (dev); /* Ignore errors. Perhaps it's not fatal. */ grub_errno = GRUB_ERR_NONE; boot_drive = drive; boot_part_addr = part_addr; grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 1); return; fail: if (file) grub_file_close (file); grub_dl_unref (my_mod); }
static int grub_ext2_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR (*hook) (const char *filename, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node)) { unsigned int fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; if (! diro->inode_read) { grub_ext2_read_inode (diro->data, diro->ino, &diro->inode); if (grub_errno) return 0; } /* Search the file. */ while (fpos < grub_le_to_cpu32 (diro->inode.size)) { struct ext2_dirent dirent; grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent), (char *) &dirent); if (grub_errno) return 0; if (dirent.direntlen == 0) return 0; if (dirent.namelen != 0) { char filename[dirent.namelen + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent), dirent.namelen, filename); if (grub_errno) return 0; fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); if (! fdiro) return 0; fdiro->data = diro->data; fdiro->ino = grub_le_to_cpu32 (dirent.inode); filename[dirent.namelen] = '\0'; if (dirent.filetype != FILETYPE_UNKNOWN) { fdiro->inode_read = 0; if (dirent.filetype == FILETYPE_DIRECTORY) type = GRUB_FSHELP_DIR; else if (dirent.filetype == FILETYPE_SYMLINK) type = GRUB_FSHELP_SYMLINK; else if (dirent.filetype == FILETYPE_REG) type = GRUB_FSHELP_REG; } else { /* The filetype can not be read from the dirent, read the inode to get more information. */ grub_ext2_read_inode (diro->data, grub_le_to_cpu32 (dirent.inode), &fdiro->inode); if (grub_errno) { grub_free (fdiro); return 0; } fdiro->inode_read = 1; if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY) type = GRUB_FSHELP_DIR; else if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK) type = GRUB_FSHELP_SYMLINK; else if ((grub_le_to_cpu16 (fdiro->inode.mode) & FILETYPE_INO_MASK) == FILETYPE_INO_REG) type = GRUB_FSHELP_REG; } if (hook (filename, type, fdiro)) return 1; } fpos += grub_le_to_cpu16 (dirent.direntlen); } return 0; }
static grub_disk_addr_t grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_ext2_data *data = node->data; struct grub_ext2_inode *inode = &node->inode; int blknr = -1; unsigned int blksz = EXT2_BLOCK_SIZE (data); int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) { char buf[EXT2_BLOCK_SIZE(data)]; struct grub_ext4_extent_header *leaf; struct grub_ext4_extent *ext; int i; leaf = grub_ext4_find_leaf (data, buf, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock); if (! leaf) { grub_error (GRUB_ERR_BAD_FS, "invalid extent"); return -1; } ext = (struct grub_ext4_extent *) (leaf + 1); for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++) { if (fileblock < grub_le_to_cpu32 (ext[i].block)) break; } if (--i >= 0) { fileblock -= grub_le_to_cpu32 (ext[i].block); if (fileblock >= grub_le_to_cpu16 (ext[i].len)) return 0; else { grub_disk_addr_t start; start = grub_le_to_cpu16 (ext[i].start_hi); start = (start << 32) + grub_le_to_cpu32 (ext[i].start); return fileblock + start; } } else { grub_error (GRUB_ERR_BAD_FS, "something wrong with extent"); return -1; } } /* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); /* Indirect. */ else if (fileblock < INDIRECT_BLOCKS + blksz / 4) { grub_uint32_t indir[blksz / 4]; if (grub_disk_read (data->disk, ((grub_disk_addr_t) grub_le_to_cpu32 (inode->blocks.indir_block)) << log2_blksz, 0, blksz, indir)) return grub_errno; blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]); } /* Double indirect. */ else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)) { unsigned int perblock = blksz / 4; unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4); grub_uint32_t indir[blksz / 4]; if (grub_disk_read (data->disk, ((grub_disk_addr_t) grub_le_to_cpu32 (inode->blocks.double_indir_block)) << log2_blksz, 0, blksz, indir)) return grub_errno; if (grub_disk_read (data->disk, ((grub_disk_addr_t) grub_le_to_cpu32 (indir[rblock / perblock])) << log2_blksz, 0, blksz, indir)) return grub_errno; blknr = grub_le_to_cpu32 (indir[rblock % perblock]); } /* triple indirect. */ else { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ext2fs doesn't support triple indirect blocks"); } return blknr; }
static grub_err_t grub_linux_boot (void) { grub_err_t err = 0; const char *modevar; char *tmp; struct grub_relocator32_state state; void *real_mode_mem; struct grub_linux_boot_ctx ctx = { .real_mode_target = 0 }; grub_size_t mmap_size; grub_size_t cl_offset; #ifdef GRUB_MACHINE_IEEE1275 { const char *bootpath; grub_ssize_t len; bootpath = grub_env_get ("root"); if (bootpath) grub_ieee1275_set_property (grub_ieee1275_chosen, "bootpath", bootpath, grub_strlen (bootpath) + 1, &len); linux_params.ofw_signature = GRUB_LINUX_OFW_SIGNATURE; linux_params.ofw_num_items = 1; linux_params.ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn; linux_params.ofw_idt = 0; } #endif modevar = grub_env_get ("gfxpayload"); /* Now all graphical modes are acceptable. May change in future if we have modes without framebuffer. */ if (modevar && *modevar != 0) { tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); if (! tmp) return grub_errno; #if ACCEPTS_PURE_TEXT err = grub_video_set_mode (tmp, 0, 0); #else err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); #endif grub_free (tmp); } else /* We can't go back to text mode from coreboot fb. */ #ifdef GRUB_MACHINE_COREBOOT if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT) err = GRUB_ERR_NONE; else #endif { #if ACCEPTS_PURE_TEXT err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); #else err = grub_video_set_mode (DEFAULT_VIDEO_MODE, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); #endif } if (err) { grub_print_error (); grub_puts_ (N_("Booting in blind mode")); grub_errno = GRUB_ERR_NONE; } if (grub_linux_setup_video (&linux_params)) { #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) linux_params.have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT; linux_params.video_mode = 0x3; #else linux_params.have_vga = 0; linux_params.video_mode = 0; linux_params.video_width = 0; linux_params.video_height = 0; #endif } #ifndef GRUB_MACHINE_IEEE1275 if (linux_params.have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT) #endif { grub_term_output_t term; int found = 0; FOR_ACTIVE_TERM_OUTPUTS(term) if (grub_strcmp (term->name, "vga_text") == 0 || grub_strcmp (term->name, "console") == 0 || grub_strcmp (term->name, "ofconsole") == 0) { struct grub_term_coordinate pos = grub_term_getxy (term); linux_params.video_cursor_x = pos.x; linux_params.video_cursor_y = pos.y; linux_params.video_width = grub_term_width (term); linux_params.video_height = grub_term_height (term); found = 1; break; } if (!found) { linux_params.video_cursor_x = 0; linux_params.video_cursor_y = 0; linux_params.video_width = 80; linux_params.video_height = 25; } } mmap_size = find_mmap_size (); /* Make sure that each size is aligned to a page boundary. */ cl_offset = ALIGN_UP (mmap_size + sizeof (linux_params), 4096); if (cl_offset < ((grub_size_t) linux_params.setup_sects << GRUB_DISK_SECTOR_BITS)) cl_offset = ALIGN_UP ((grub_size_t) (linux_params.setup_sects << GRUB_DISK_SECTOR_BITS), 4096); ctx.real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096); #ifdef GRUB_MACHINE_EFI efi_mmap_size = find_efi_mmap_size (); if (efi_mmap_size == 0) return grub_errno; #endif grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n", (unsigned) ctx.real_size, (unsigned) mmap_size); #ifdef GRUB_MACHINE_EFI grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 1); if (! ctx.real_mode_target) grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 0); #else grub_mmap_iterate (grub_linux_boot_mmap_find, &ctx); #endif grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n", (unsigned long) ctx.real_mode_target, (unsigned) ctx.real_size, (unsigned) efi_mmap_size); if (! ctx.real_mode_target) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages"); { grub_relocator_chunk_t ch; err = grub_relocator_alloc_chunk_addr (relocator, &ch, ctx.real_mode_target, (ctx.real_size + efi_mmap_size)); if (err) return err; real_mode_mem = get_virtual_current_address (ch); } efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size; grub_dprintf ("linux", "real_mode_mem = %p\n", real_mode_mem); ctx.params = real_mode_mem; *ctx.params = linux_params; ctx.params->cmd_line_ptr = ctx.real_mode_target + cl_offset; grub_memcpy ((char *) ctx.params + cl_offset, linux_cmdline, maximal_cmdline_size); grub_dprintf ("linux", "code32_start = %x\n", (unsigned) ctx.params->code32_start); ctx.e820_num = 0; if (grub_mmap_iterate (grub_linux_boot_mmap_fill, &ctx)) return grub_errno; ctx.params->mmap_size = ctx.e820_num; #ifdef GRUB_MACHINE_EFI { grub_efi_uintn_t efi_desc_size; grub_size_t efi_mmap_target; grub_efi_uint32_t efi_desc_version; err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL, &efi_desc_size, &efi_desc_version); if (err) return err; /* Note that no boot services are available from here. */ efi_mmap_target = ctx.real_mode_target + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem); /* Pass EFI parameters. */ if (grub_le_to_cpu16 (ctx.params->version) >= 0x0208) { ctx.params->v0208.efi_mem_desc_size = efi_desc_size; ctx.params->v0208.efi_mem_desc_version = efi_desc_version; ctx.params->v0208.efi_mmap = efi_mmap_target; ctx.params->v0208.efi_mmap_size = efi_mmap_size; #ifdef __x86_64__ ctx.params->v0208.efi_mmap_hi = (efi_mmap_target >> 32); #endif } else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0206)
static grub_err_t grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) { grub_file_t file = 0; grub_elf_t elf = 0; grub_err_t err; int type = -1, i; int ret = 0; grub_macho_t macho = 0; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); for (i = OPT_TYPE_MIN; i <= OPT_TYPE_MAX; i++) if (ctxt->state[i].set) { if (type == -1) { type = i; continue; } return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple types specified"); } if (type == -1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no type specified"); file = grub_file_open (args[0]); if (!file) return grub_errno; switch (type) { case IS_BIOS_BOOTSECTOR: { grub_uint16_t sig; if (grub_file_size (file) != 512) break; if (grub_file_seek (file, 510) == (grub_size_t) -1) break; if (grub_file_read (file, &sig, 2) != 2) break; if (sig != grub_cpu_to_le16_compile_time (0xaa55)) break; ret = 1; break; } case IS_IA64_LINUX: { Elf64_Ehdr ehdr; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 || ehdr.e_ident[EI_DATA] != ELFDATA2LSB || ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_IA_64)) break; ret = 1; break; } case IS_SPARC64_LINUX: { Elf64_Ehdr ehdr; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 || ehdr.e_ident[EI_DATA] != ELFDATA2MSB) break; if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_SPARCV9) || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) break; ret = 1; break; } case IS_POWERPC_LINUX: { Elf32_Ehdr ehdr; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB || (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_PPC) && ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_PPC64))) break; if (ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC) && ehdr.e_type != grub_cpu_to_be16_compile_time (ET_DYN)) break; ret = 1; break; } case IS_MIPS_LINUX: { Elf32_Ehdr ehdr; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB || ehdr.e_machine != grub_cpu_to_be16_compile_time (EM_MIPS) || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) break; ret = 1; break; } case IS_X86_KNETBSD: case IS_X86_KNETBSD32: case IS_X86_KNETBSD64: { int is32, is64; elf = grub_elf_file (file, file->name); if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) || elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB) break; is32 = grub_elf_is_elf32 (elf); is64 = grub_elf_is_elf64 (elf); if (!is32 && !is64) break; if (!is32 && type == IS_X86_KNETBSD32) break; if (!is64 && type == IS_X86_KNETBSD64) break; if (is64) ret = grub_file_check_netbsd64 (elf); if (is32) ret = grub_file_check_netbsd32 (elf); break; } case IS_X86_KFREEBSD: case IS_X86_KFREEBSD32: case IS_X86_KFREEBSD64: { Elf32_Ehdr ehdr; int is32, is64; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) || ehdr.e_ident[EI_DATA] != ELFDATA2LSB) break; if (ehdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD) break; is32 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_386) && ehdr.e_ident[EI_CLASS] == ELFCLASS32); is64 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_X86_64) && ehdr.e_ident[EI_CLASS] == ELFCLASS64); if (!is32 && !is64) break; if (!is32 && (type == IS_X86_KFREEBSD32 || type == IS_X86_KNETBSD32)) break; if (!is64 && (type == IS_X86_KFREEBSD64 || type == IS_X86_KNETBSD64)) break; ret = 1; break; } case IS_MIPSEL_LINUX: { Elf32_Ehdr ehdr; if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) break; if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3 || ehdr.e_ident[EI_VERSION] != EV_CURRENT || ehdr.e_version != EV_CURRENT) break; if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_MIPS) || ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)) break; ret = 1; break; } case IS_ARM_LINUX: { grub_uint32_t sig, sig_pi; if (grub_file_read (file, &sig_pi, 4) != 4) break; /* Raspberry pi. */ if (sig_pi == grub_cpu_to_le32_compile_time (0xea000006)) { ret = 1; break; } if (grub_file_seek (file, 0x24) == (grub_size_t) -1) break; if (grub_file_read (file, &sig, 4) != 4) break; if (sig == grub_cpu_to_le32_compile_time (0x016f2818)) { ret = 1; break; } break; } case IS_ARM64_LINUX: { grub_uint32_t sig; if (grub_file_seek (file, 0x38) == (grub_size_t) -1) break; if (grub_file_read (file, &sig, 4) != 4) break; if (sig == grub_cpu_to_le32_compile_time (0x644d5241)) { ret = 1; break; } break; } case IS_PAE_DOMU ... IS_DOM0: { struct grub_xen_file_info xen_inf; elf = grub_xen_file (file); if (!elf) break; err = grub_xen_get_info (elf, &xen_inf); if (err) break; /* Unfortuntely no way to check if kernel supports dom0. */ if (type == IS_DOM0) ret = 1; if (type == IS_PAE_DOMU) ret = (xen_inf.arch == GRUB_XEN_FILE_I386_PAE || xen_inf.arch == GRUB_XEN_FILE_I386_PAE_BIMODE); if (type == IS_64_DOMU) ret = (xen_inf.arch == GRUB_XEN_FILE_X86_64); break; } case IS_MULTIBOOT: case IS_MULTIBOOT2: { grub_uint32_t *buffer; grub_ssize_t len; grub_size_t search_size; grub_uint32_t *header; grub_uint32_t magic; grub_size_t step; if (type == IS_MULTIBOOT2) { search_size = 32768; magic = grub_cpu_to_le32_compile_time (0xe85250d6); step = 2; } else { search_size = 8192; magic = grub_cpu_to_le32_compile_time (0x1BADB002); step = 1; } buffer = grub_malloc (search_size); if (!buffer) break; len = grub_file_read (file, buffer, search_size); if (len < 32) { grub_free (buffer); break; } /* Look for the multiboot header in the buffer. The header should be at least 12 bytes and aligned on a 4-byte boundary. */ for (header = buffer; ((char *) header <= (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12)) || (header = 0); header += step) { if (header[0] == magic && !(grub_le_to_cpu32 (header[0]) + grub_le_to_cpu32 (header[1]) + grub_le_to_cpu32 (header[2]) + (type == IS_MULTIBOOT2 ? grub_le_to_cpu32 (header[3]) : 0))) break; } if (header != 0) ret = 1; grub_free (buffer); break; } case IS_X86_LINUX32: case IS_X86_LINUX: { struct linux_kernel_header lh; if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) break; if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) break; if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) break; /* FIXME: some really old kernels (< 1.3.73) will fail this. */ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) || grub_le_to_cpu16 (lh.version) < 0x0200) break; if (type == IS_X86_LINUX) { ret = 1; break; } /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and still not support 32-bit boot. */ if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE) || grub_le_to_cpu16 (lh.version) < 0x0203) break; if (!(lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL)) break; ret = 1; break; } case IS_HIBERNATED: { grub_uint8_t hibr_file_magic[4]; if (grub_file_read (file, &hibr_file_magic, sizeof (hibr_file_magic)) != sizeof (hibr_file_magic)) break; if (grub_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) == 0 || grub_memcmp ("HIBR", hibr_file_magic, sizeof (hibr_file_magic)) == 0) ret = 1; break; } case IS_XNU64: case IS_XNU32: { macho = grub_macho_open (args[0], (type == IS_XNU64)); if (!macho) break; /* FIXME: more checks? */ ret = 1; break; } case IS_XNU_HIBR: { struct grub_xnu_hibernate_header hibhead; if (grub_file_read (file, &hibhead, sizeof (hibhead)) != sizeof (hibhead)) break; if (hibhead.magic != grub_cpu_to_le32_compile_time (GRUB_XNU_HIBERNATE_MAGIC)) break; ret = 1; break; } case IS_32_EFI: case IS_64_EFI: case IS_IA_EFI: case IS_ARM64_EFI: case IS_ARM_EFI: { char signature[4]; grub_uint32_t pe_offset; struct grub_pe32_coff_header coff_head; if (grub_file_read (file, signature, 2) != 2) break; if (signature[0] != 'M' || signature[1] != 'Z') break; if ((grub_ssize_t) grub_file_seek (file, 0x3c) == -1) break; if (grub_file_read (file, &pe_offset, 4) != 4) break; if ((grub_ssize_t) grub_file_seek (file, grub_le_to_cpu32 (pe_offset)) == -1) break; if (grub_file_read (file, signature, 4) != 4) break; if (signature[0] != 'P' || signature[1] != 'E' || signature[2] != '\0' || signature[3] != '\0') break; if (grub_file_read (file, &coff_head, sizeof (coff_head)) != sizeof (coff_head)) break; if (type == IS_32_EFI && coff_head.machine != grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_I386)) break; if (type == IS_64_EFI && coff_head.machine != grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_X86_64)) break; if (type == IS_IA_EFI && coff_head.machine != grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_IA64)) break; if (type == IS_ARM64_EFI && coff_head.machine != grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARM64)) break; if (type == IS_ARM_EFI && coff_head.machine != grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED)) break; if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI) { struct grub_pe64_optional_header o64; if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64)) break; if (o64.magic != grub_cpu_to_le16_compile_time (GRUB_PE32_PE64_MAGIC)) break; if (o64.subsystem != grub_cpu_to_le16_compile_time (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) break; ret = 1; break; } if (type == IS_32_EFI || type == IS_ARM_EFI) { struct grub_pe32_optional_header o32; if (grub_file_read (file, &o32, sizeof (o32)) != sizeof (o32)) break; if (o32.magic != grub_cpu_to_le16_compile_time (GRUB_PE32_PE32_MAGIC)) break; if (o32.subsystem != grub_cpu_to_le16_compile_time (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) break; ret = 1; break; } break; } } if (elf) grub_elf_close (elf); else if (macho) grub_macho_close (macho); else if (file) grub_file_close (file); if (!ret && (grub_errno == GRUB_ERR_BAD_OS || grub_errno == GRUB_ERR_NONE)) /* TRANSLATORS: it's a standalone boolean value, opposite of "true". */ grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); return grub_errno; }
static char * get_btrfs_fs_prefix (const char *mount_path) { struct btrfs_ioctl_ino_lookup_args args; struct stat st; int fd; grub_uint64_t tree_id, inode_id; char *ret = NULL; fd = open (mount_path, O_RDONLY); if (fd < 0) return NULL; memset (&args, 0, sizeof(args)); args.objectid = GRUB_BTRFS_TREE_ROOT_OBJECTID; if (ioctl (fd, BTRFS_IOC_INO_LOOKUP, &args) < 0) goto fail; tree_id = args.treeid; if (fstat (fd, &st) < 0) goto fail; inode_id = st.st_ino; while (tree_id != GRUB_BTRFS_ROOT_VOL_OBJECTID || inode_id != GRUB_BTRFS_TREE_ROOT_OBJECTID) { const char *name; size_t namelen; struct btrfs_ioctl_search_args sargs; char *old; memset (&sargs, 0, sizeof(sargs)); if (inode_id == GRUB_BTRFS_TREE_ROOT_OBJECTID) { struct grub_btrfs_root_backref *br; sargs.key.tree_id = 1; sargs.key.min_objectid = tree_id; sargs.key.max_objectid = tree_id; sargs.key.min_offset = 0; sargs.key.max_offset = ~0ULL; sargs.key.min_transid = 0; sargs.key.max_transid = ~0ULL; sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF; sargs.key.nr_items = 1; if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0) goto fail; if (sargs.key.nr_items == 0) goto fail; tree_id = sargs.buf[2]; br = (struct grub_btrfs_root_backref *) (sargs.buf + 4); inode_id = grub_le_to_cpu64 (br->inode_id); name = br->name; namelen = grub_le_to_cpu16 (br->n); } else { struct grub_btrfs_inode_ref *ir; sargs.key.tree_id = tree_id; sargs.key.min_objectid = inode_id; sargs.key.max_objectid = inode_id; sargs.key.min_offset = 0; sargs.key.max_offset = ~0ULL; sargs.key.min_transid = 0; sargs.key.max_transid = ~0ULL; sargs.key.min_type = GRUB_BTRFS_ITEM_TYPE_INODE_REF; sargs.key.max_type = GRUB_BTRFS_ITEM_TYPE_INODE_REF; if (ioctl (fd, BTRFS_IOC_TREE_SEARCH, &sargs) < 0) goto fail; if (sargs.key.nr_items == 0) goto fail; inode_id = sargs.buf[2]; ir = (struct grub_btrfs_inode_ref *) (sargs.buf + 4); name = ir->name; namelen = grub_le_to_cpu16 (ir->n); } old = ret; ret = xmalloc (namelen + (old ? strlen (old) : 0) + 2); ret[0] = '/'; memcpy (ret + 1, name, namelen); if (old) { strcpy (ret + 1 + namelen, old); free (old); } else ret[1+namelen] = '\0'; } if (!ret) ret = xstrdup ("/"); close (fd); return ret; fail: free (ret); close (fd); return NULL; }
static void probe (const char *path, char **device_names, char delim) { char **drives_names = NULL; char **curdev, **curdrive; char *grub_path = NULL; int ndev = 0; if (path != NULL) { grub_path = canonicalize_file_name (path); if (! grub_path) grub_util_error (_("failed to get canonical path of `%s'"), path); device_names = grub_guess_root_devices (grub_path); free (grub_path); } if (! device_names) grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path); if (print == PRINT_DEVICE) { for (curdev = device_names; *curdev; curdev++) { printf ("%s", *curdev); putchar (delim); } return; } if (print == PRINT_DISK) { for (curdev = device_names; *curdev; curdev++) { char *disk; disk = grub_util_get_os_disk (*curdev); if (!disk) { grub_print_error (); continue; } printf ("%s", disk); putchar (delim); } return; } for (curdev = device_names; *curdev; curdev++) { grub_util_pull_device (*curdev); ndev++; } drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); for (curdev = device_names, curdrive = drives_names; *curdev; curdev++, curdrive++) { *curdrive = grub_util_get_grub_dev (*curdev); if (! *curdrive) grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), *curdev); } *curdrive = 0; if (print == PRINT_DRIVE) { for (curdrive = drives_names; *curdrive; curdrive++) { printf ("(%s)", *curdrive); putchar (delim); } goto end; } if (print == PRINT_ZERO_CHECK) { for (curdev = drives_names; *curdev; curdev++) { grub_device_t dev = NULL; grub_uint32_t buffer[32768]; grub_disk_addr_t addr; grub_disk_addr_t dsize; grub_util_info ("opening %s", *curdev); dev = grub_device_open (*curdev); if (! dev || !dev->disk) grub_util_error ("%s", grub_errmsg); dsize = grub_disk_get_size (dev->disk); for (addr = 0; addr < dsize; addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE) { grub_size_t sz = sizeof (buffer); grub_uint32_t *ptr; if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr) sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE; grub_disk_read (dev->disk, addr, 0, sz, buffer); for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++) if (*ptr) { grub_printf ("false\n"); grub_device_close (dev); goto end; } } grub_device_close (dev); } grub_printf ("true\n"); } if (print == PRINT_FS || print == PRINT_FS_UUID || print == PRINT_FS_LABEL) { grub_device_t dev = NULL; grub_fs_t fs; grub_util_info ("opening %s", drives_names[0]); dev = grub_device_open (drives_names[0]); if (! dev) grub_util_error ("%s", grub_errmsg); fs = grub_fs_probe (dev); if (! fs) grub_util_error ("%s", grub_errmsg); if (print == PRINT_FS) { printf ("%s", fs->name); putchar (delim); } else if (print == PRINT_FS_UUID) { char *uuid; if (! fs->uuid) grub_util_error (_("%s does not support UUIDs"), fs->name); if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); printf ("%s", uuid); putchar (delim); } else if (print == PRINT_FS_LABEL) { char *label; if (! fs->label) grub_util_error (_("filesystem `%s' does not support labels"), fs->name); if (fs->label (dev, &label) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); printf ("%s", label); putchar (delim); } grub_device_close (dev); goto end; } for (curdrive = drives_names, curdev = device_names; *curdrive; curdrive++, curdev++) { grub_device_t dev = NULL; grub_util_info ("opening %s", *curdrive); dev = grub_device_open (*curdrive); if (! dev) grub_util_error ("%s", grub_errmsg); if (print == PRINT_HINT_STR) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; char *biosname, *bare, *efi; const char *map; if (ofpath) { char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/")); char *p; p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); printf ("--hint-ieee1275='"); print_full_name (tmp, dev); printf ("' "); free (tmp); } biosname = guess_bios_drive (*curdev); if (biosname) { printf ("--hint-bios="); print_full_name (biosname, dev); printf (" "); } free (biosname); efi = guess_efi_drive (*curdev); if (efi) { printf ("--hint-efi="); print_full_name (efi, dev); printf (" "); } free (efi); bare = guess_baremetal_drive (*curdev); if (bare) { printf ("--hint-baremetal="); print_full_name (bare, dev); printf (" "); } free (bare); /* FIXME: Add ARC hint. */ map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { printf ("--hint='"); print_full_name (map, dev); printf ("' "); } if (curdrive[1]) printf (" "); else printf ("\n"); grub_device_close (dev); continue; } if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) { print_full_name (dev->disk->name, dev); putchar (delim); continue; } if (print == PRINT_COMPATIBILITY_HINT) { const char *map; char *biosname; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); grub_device_close (dev); /* Compatibility hint is one device only. */ break; } biosname = guess_bios_drive (*curdev); if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); /* Compatibility hint is one device only. */ if (biosname) break; continue; } if (print == PRINT_BIOS_HINT) { char *biosname; biosname = guess_bios_drive (*curdev); if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_IEEE1275_HINT) { const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); const char *ofpath = grub_util_devname_to_ofpath (osdev); const char *map; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (ofpath) { char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/")); char *p; p = grub_stpcpy (tmp, "ieee1275/"); strcpy (p, ofpath); print_full_name (tmp, dev); free (tmp); putchar (delim); } grub_device_close (dev); continue; } if (print == PRINT_EFI_HINT) { char *biosname; const char *map; biosname = guess_efi_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_BAREMETAL_HINT) { char *biosname; const char *map; biosname = guess_baremetal_drive (*curdev); map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } if (biosname) { print_full_name (biosname, dev); putchar (delim); } free (biosname); grub_device_close (dev); continue; } if (print == PRINT_ARC_HINT) { const char *map; map = grub_util_biosdisk_get_compatibility_hint (dev->disk); if (map) { print_full_name (map, dev); putchar (delim); } /* FIXME */ grub_device_close (dev); continue; } if (print == PRINT_ABSTRACTION) { probe_abstraction (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_CRYPTODISK_UUID) { probe_cryptodisk_uuid (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_PARTMAP) { /* Check if dev->disk itself is contained in a partmap. */ probe_partmap (dev->disk); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_MSDOS_PARTTYPE) { if (dev->disk->partition && strcmp(dev->disk->partition->partmap->name, "msdos") == 0) printf ("%02x", dev->disk->partition->msdostype); putchar (delim); grub_device_close (dev); continue; } if (print == PRINT_GPT_PARTTYPE) { if (dev->disk->partition && strcmp (dev->disk->partition->partmap->name, "gpt") == 0) { struct grub_gpt_partentry gptdata; grub_partition_t p = dev->disk->partition; dev->disk->partition = dev->disk->partition->parent; if (grub_disk_read (dev->disk, p->offset, p->index, sizeof (gptdata), &gptdata) == 0) { grub_gpt_part_type_t gpttype; gpttype.data1 = grub_le_to_cpu32 (gptdata.type.data1); gpttype.data2 = grub_le_to_cpu16 (gptdata.type.data2); gpttype.data3 = grub_le_to_cpu16 (gptdata.type.data3); grub_memcpy (gpttype.data4, gptdata.type.data4, 8); grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", gpttype.data1, gpttype.data2, gpttype.data3, gpttype.data4[0], gpttype.data4[1], gpttype.data4[2], gpttype.data4[3], gpttype.data4[4], gpttype.data4[5], gpttype.data4[6], gpttype.data4[7]); } dev->disk->partition = p; } putchar (delim); grub_device_close (dev); continue; } } end: for (curdrive = drives_names; *curdrive; curdrive++) free (*curdrive); free (drives_names); }
static grub_err_t grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, grub_disk_addr_t *start_sector) { grub_disk_addr_t sector = 0; grub_uint64_t size; struct grub_raid_super_1x sb; grub_uint8_t minor_version; /* The sector where the mdraid 0.90 superblock is stored, if available. */ size = grub_disk_get_size (disk); /* Check for an 1.x superblock. * It's always aligned to a 4K boundary * and depending on the minor version it can be: * 0: At least 8K, but less than 12K, from end of device * 1: At start of device * 2: 4K from start of device. */ for (minor_version = 0; minor_version < 3; ++minor_version) { if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) continue; switch (minor_version) { case 0: sector = (size - 8 * 2) & ~(4 * 2 - 1); break; case 1: sector = 0; break; case 2: sector = 4 * 2; break; } if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x), &sb)) return grub_errno; if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC || grub_le_to_cpu64 (sb.super_offset) != sector) continue; { grub_uint64_t sb_size; struct grub_raid_super_1x *real_sb; grub_uint32_t level; if (grub_le_to_cpu32 (sb.major_version) != 1) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported RAID version: %d", grub_le_to_cpu32 (sb.major_version)); level = grub_le_to_cpu32 (sb.level); /* Multipath. */ if ((int) level == -4) level = 1; if (level != 0 && level != 1 && level != 4 && level != 5 && level != 6 && level != 10) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported RAID level: %d", sb.level); /* 1.x superblocks don't have a fixed size on disk. So we have to read it again now that we now the max device count. */ sb_size = sizeof (struct grub_raid_super_1x) + 2 * grub_le_to_cpu32 (sb.max_dev); real_sb = grub_malloc (sb_size); if (! real_sb) return grub_errno; if (grub_disk_read (disk, sector, 0, sb_size, real_sb)) { grub_free (real_sb); return grub_errno; } array->name = grub_strdup (real_sb->set_name); if (! array->name) { grub_free (real_sb); return grub_errno; } array->number = 0; array->level = grub_le_to_cpu32 (real_sb->level); array->layout = grub_le_to_cpu32 (real_sb->layout); array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); array->disk_size = grub_le_to_cpu64 (real_sb->size); array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); if (grub_le_to_cpu32 (real_sb->dev_number) >= grub_le_to_cpu32 (real_sb->max_dev)) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "spares aren't implemented"); array->index = grub_le_to_cpu16 (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); array->uuid_len = 16; array->uuid = grub_malloc (16); if (!array->uuid) { grub_free (real_sb); return grub_errno; } grub_memcpy (array->uuid, real_sb->set_uuid, 16); *start_sector = grub_le_to_cpu64 (real_sb->data_offset); grub_free (real_sb); return 0; } } return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid"); }
static struct grub_diskfilter_vg * grub_mdraid_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) { grub_uint64_t size; grub_uint8_t minor_version; size = grub_disk_get_size (disk); /* Check for an 1.x superblock. * It's always aligned to a 4K boundary * and depending on the minor version it can be: * 0: At least 8K, but less than 12K, from end of device * 1: At start of device * 2: 4K from start of device. */ for (minor_version = 0; minor_version < 3; ++minor_version) { grub_disk_addr_t sector = 0; struct grub_raid_super_1x sb; grub_uint16_t role; grub_uint32_t level; struct grub_diskfilter_vg *array; char *uuid; if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) continue; switch (minor_version) { case 0: sector = (size - 8 * 2) & ~(4 * 2 - 1); break; case 1: sector = 0; break; case 2: sector = 4 * 2; break; } if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x), &sb)) return NULL; if (sb.magic != grub_cpu_to_le32_compile_time (SB_MAGIC) || grub_le_to_cpu64 (sb.super_offset) != sector) continue; if (sb.major_version != grub_cpu_to_le32_compile_time (1)) /* Unsupported version. */ return NULL; level = grub_le_to_cpu32 (sb.level); /* Multipath. */ if ((int) level == -4) level = 1; if (level != 0 && level != 1 && level != 4 && level != 5 && level != 6 && level != 10) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported RAID level: %d", sb.level); return NULL; } if (grub_le_to_cpu32 (sb.dev_number) >= grub_le_to_cpu32 (sb.max_dev)) /* Spares aren't implemented. */ return NULL; if (grub_disk_read (disk, sector, (char *) &sb.dev_roles[grub_le_to_cpu32 (sb.dev_number)] - (char *) &sb, sizeof (role), &role)) return NULL; if (grub_le_to_cpu16 (role) >= grub_le_to_cpu32 (sb.raid_disks)) /* Spares aren't implemented. */ return NULL; id->uuidlen = 0; id->id = grub_le_to_cpu16 (role); uuid = grub_malloc (16); if (!uuid) return NULL; grub_memcpy (uuid, sb.set_uuid, 16); *start_sector = grub_le_to_cpu64 (sb.data_offset); array = grub_diskfilter_make_raid (16, uuid, grub_le_to_cpu32 (sb.raid_disks), sb.set_name, (sb.size) ? grub_le_to_cpu64 (sb.size) : grub_le_to_cpu64 (sb.data_size), grub_le_to_cpu32 (sb.chunksize), grub_le_to_cpu32 (sb.layout), grub_le_to_cpu32 (sb.level)); return array; } /* not 1.x raid. */ return NULL; }
static grub_err_t grub_video_reader_tga (struct grub_video_bitmap **bitmap, const char *filename) { grub_ssize_t pos; struct tga_data data; grub_memset (&data, 0, sizeof (data)); data.file = grub_buffile_open (filename, 0); if (! data.file) return grub_errno; /* TGA Specification states that we SHOULD start by reading ID from end of file, but we really don't care about that as we are not going to support developer area & extensions at this point. */ /* Read TGA header from beginning of file. */ if (grub_file_read (data.file, &data.hdr, sizeof (data.hdr)) != sizeof (data.hdr)) { grub_file_close (data.file); return grub_errno; } /* Skip ID field. */ pos = grub_file_tell (data.file); pos += data.hdr.id_length; grub_file_seek (data.file, pos); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } grub_dprintf("tga", "tga: header\n"); dump_int_field(data.hdr.id_length); dump_int_field(data.hdr.color_map_type); dump_int_field(data.hdr.image_type); dump_int_field(data.hdr.color_map_first_index); dump_int_field(data.hdr.color_map_length); dump_int_field(data.hdr.color_map_bpp); dump_int_field(data.hdr.image_x_origin); dump_int_field(data.hdr.image_y_origin); dump_int_field(data.hdr.image_width); dump_int_field(data.hdr.image_height); dump_int_field(data.hdr.image_bpp); dump_int_field(data.hdr.image_descriptor); data.image_width = grub_le_to_cpu16 (data.hdr.image_width); data.image_height = grub_le_to_cpu16 (data.hdr.image_height); /* Check that bitmap encoding is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: data.uses_rle = 1; break; case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: data.uses_rle = 0; break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (unknown encoding %d)", data.hdr.image_type); } data.bpp = data.hdr.image_bpp / 8; /* Check that bitmap depth is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: if (data.hdr.image_bpp != 8) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_grayscale (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: if (data.hdr.image_bpp != 8 || data.hdr.color_map_bpp != 24 || data.hdr.color_map_first_index != 0) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_palette (&data); tga_load_index_color (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: switch (data.hdr.image_bpp) { case 24: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8 (&data); break; case 32: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGBA_8888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8A8 (&data); break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } } /* If there was a loading problem, destroy bitmap. */ if (grub_errno != GRUB_ERR_NONE) { grub_video_bitmap_destroy (*bitmap); *bitmap = 0; } grub_file_close (data.file); return grub_errno; }