int grub_fdt_create_empty_tree (void *fdt, unsigned int size) { struct grub_fdt_empty_tree *et; if (size < GRUB_FDT_EMPTY_TREE_SZ) return -1; grub_memset (fdt, 0, size); et = fdt; et->empty_node.tree_end = grub_cpu_to_be32_compile_time (FDT_END); et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE); et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE); ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap = grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8)); grub_fdt_set_off_dt_strings (fdt, sizeof (*et)); grub_fdt_set_off_dt_struct (fdt, sizeof (et->header) + sizeof (et->empty_rsvmap)); grub_fdt_set_version (fdt, FDT_SUPPORTED_VERSION); grub_fdt_set_last_comp_version (fdt, FDT_SUPPORTED_VERSION); grub_fdt_set_size_dt_struct (fdt, sizeof (et->empty_node)); grub_fdt_set_totalsize (fdt, size); grub_fdt_set_magic (fdt, FDT_MAGIC); return 0; }
static int add_subnode (void *fdt, int parentoffset, const char *name) { grub_uint32_t *token = (void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + parentoffset); grub_uint32_t *end = (void *) struct_end (fdt); unsigned int entry_size = node_entry_size (name); unsigned int struct_size = grub_fdt_get_size_dt_struct(fdt); char *node_name; SKIP_NODE_NAME(node_name, token, end); /* Insert the new subnode just after the properties of the parent node (if any).*/ while (1) { if (token >= end) return -1; switch (grub_be_to_cpu32(*token)) { case FDT_PROP: /* Skip len, nameoff and property value. */ token += prop_entry_size(grub_be_to_cpu32(*(token + 1))) / sizeof(*token); break; case FDT_BEGIN_NODE: case FDT_END_NODE: goto insert; case FDT_NOP: token++; break; default: /* invalid token */ return -1; } } insert: grub_memmove (token + entry_size / sizeof(*token), token, (grub_addr_t) end - (grub_addr_t) token); *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE); token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ grub_strcpy((char *) (token + 1), name); token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE); grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size); return ((grub_addr_t) token - (grub_addr_t) fdt - grub_fdt_get_off_dt_struct(fdt)); }
static int validate_head (struct cbfs_header *head) { return (head->magic == grub_cpu_to_be32_compile_time (CBFS_HEADER_MAGIC) && (head->version == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION1) || head->version == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION2)) && (grub_be_to_cpu32 (head->bootblocksize) < grub_be_to_cpu32 (head->romsize)) && (grub_be_to_cpu32 (head->offset) < grub_be_to_cpu32 (head->romsize)) && (grub_be_to_cpu32 (head->offset) + grub_be_to_cpu32 (head->bootblocksize) < grub_be_to_cpu32 (head->romsize)) && head->align != 0 && (head->align & (head->align - 1)) == 0 && head->romsize != 0); }
/* Mount the filesystem on the disk DISK. */ static struct grub_hfs_data * grub_hfs_mount (grub_disk_t disk) { struct grub_hfs_data *data; struct grub_hfs_catalog_key key; struct grub_hfs_dirrec dir; int first_block; struct { struct grub_hfs_node node; struct grub_hfs_treeheader head; } treehead; data = grub_malloc (sizeof (struct grub_hfs_data)); if (!data) return 0; /* Read the superblock. */ if (grub_disk_read (disk, GRUB_HFS_SBLOCK, 0, sizeof (struct grub_hfs_sblock), &data->sblock)) goto fail; /* Check if this is a HFS filesystem. */ if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC || (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff))) { grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem"); goto fail; } /* Check if this is an embedded HFS+ filesystem. */ if (grub_be_to_cpu16 (data->sblock.embed_sig) == GRUB_HFS_EMBED_HFSPLUS_SIG) { grub_error (GRUB_ERR_BAD_FS, "embedded HFS+ filesystem"); goto fail; } data->blksz = grub_be_to_cpu32 (data->sblock.blksz); data->disk = disk; /* Lookup the root node of the extent overflow tree. */ first_block = ((grub_be_to_cpu16 (data->sblock.extent_recs[0].first_block) * GRUB_HFS_BLKS) + grub_be_to_cpu16 (data->sblock.first_block)); if (grub_disk_read (data->disk, first_block, 0, sizeof (treehead), &treehead)) goto fail; data->ext_root = grub_be_to_cpu32 (treehead.head.root_node); data->ext_size = grub_be_to_cpu16 (treehead.head.node_size); /* Lookup the root node of the catalog tree. */ first_block = ((grub_be_to_cpu16 (data->sblock.catalog_recs[0].first_block) * GRUB_HFS_BLKS) + grub_be_to_cpu16 (data->sblock.first_block)); if (grub_disk_read (data->disk, first_block, 0, sizeof (treehead), &treehead)) goto fail; data->cat_root = grub_be_to_cpu32 (treehead.head.root_node); data->cat_size = grub_be_to_cpu16 (treehead.head.node_size); /* Lookup the root directory node in the catalog tree using the volume name. */ key.parent_dir = grub_cpu_to_be32 (1); key.strlen = data->sblock.volname[0]; grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1)); if (grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &dir, sizeof (dir)) == 0) { grub_error (GRUB_ERR_BAD_FS, "cannot find the HFS root directory"); goto fail; } if (grub_errno) goto fail; data->rootdir = grub_be_to_cpu32 (dir.dirid); return data; fail: grub_free (data); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not a HFS filesystem"); return 0; }
int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, const void *val, grub_uint32_t len) { grub_uint32_t *prop; int prop_name_present = 0; grub_uint32_t nameoff = 0; if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) != FDT_BEGIN_NODE)) return -1; prop = find_prop (fdt, nodeoffset, name); if (prop) { grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)), sizeof(grub_uint32_t)); grub_uint32_t i; prop_name_present = 1; for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP); if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) { /* Length of new property value is greater than the space allocated for the current value: a new entry needs to be created, so save the nameoff field of the current entry and replace the current entry with NOP tokens. */ nameoff = grub_be_to_cpu32 (*(prop + 2)); *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP); prop = NULL; } } if (!prop || !prop_name_present) { unsigned int needed_space = 0; if (!prop) needed_space = prop_entry_size(len); if (!prop_name_present) needed_space += grub_strlen (name) + 1; if (needed_space > get_free_space (fdt)) return -1; if (rearrange_blocks (fdt, !prop ? prop_entry_size(len) : 0) < 0) return -1; } if (!prop_name_present) { /* Append the property name at the end of the strings block. */ nameoff = grub_fdt_get_size_dt_strings (fdt); grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff, name); grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt) + grub_strlen (name) + 1); } if (!prop) { char *node_name = (char *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct (fdt) + nodeoffset + sizeof(grub_uint32_t)); prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4)); grub_memmove (prop + prop_entry_size(len) / sizeof(*prop), prop, struct_end(fdt) - (grub_addr_t) prop); grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + prop_entry_size(len)); *prop = grub_cpu_to_be32_compile_time (FDT_PROP); *(prop + 2) = grub_cpu_to_be32 (nameoff); } *(prop + 1) = grub_cpu_to_be32 (len); /* Insert padding bytes at the end of the value; if they are not needed, they will be overwritten by the following memcpy. */ *(prop + prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0; grub_memcpy (prop + 3, val, len); return 0; }
static grub_err_t hfsplus_open_compressed_real (struct grub_hfsplus_file *node) { grub_err_t err; struct grub_hfsplus_btnode *attr_node; grub_off_t attr_off; struct grub_hfsplus_key_internal key; struct grub_hfsplus_attr_header *attr_head; struct grub_hfsplus_compress_attr *cmp_head; #define c grub_cpu_to_be16_compile_time const grub_uint16_t compress_attr_name[] = { c('c'), c('o'), c('m'), c('.'), c('a'), c('p'), c('p'), c('l'), c('e'), c('.'), c('d'), c('e'), c('c'), c('m'), c('p'), c('f'), c('s') }; #undef c if (node->size) return 0; key.attrkey.cnid = node->fileid; key.attrkey.namelen = sizeof (compress_attr_name) / sizeof (compress_attr_name[0]); key.attrkey.name = compress_attr_name; err = grub_hfsplus_btree_search (&node->data->attr_tree, &key, grub_hfsplus_cmp_attrkey, &attr_node, &attr_off); if (err || !attr_node) { grub_errno = 0; return 0; } attr_head = (struct grub_hfsplus_attr_header *) ((char *) grub_hfsplus_btree_recptr (&node->data->attr_tree, attr_node, attr_off) + sizeof (struct grub_hfsplus_attrkey) + sizeof (compress_attr_name)); if (attr_head->type != 0x10 || !(attr_head->size & grub_cpu_to_be64_compile_time(~0xfULL))) { grub_free (attr_node); return 0; } cmp_head = (struct grub_hfsplus_compress_attr *) (attr_head + 1); if (cmp_head->magic != grub_cpu_to_be32_compile_time (0x66706d63)) { grub_free (attr_node); return 0; } node->size = grub_le_to_cpu32 (cmp_head->uncompressed_inline_size); if (cmp_head->type == grub_cpu_to_le32_compile_time (HFSPLUS_COMPRESSION_RESOURCE)) { grub_uint32_t index_size; node->compressed = 2; if (grub_hfsplus_read_file (node, 0, 0, 0x104, sizeof (index_size), (char *) &index_size) != 4) { node->compressed = 0; grub_free (attr_node); grub_errno = 0; return 0; } node->compress_index_size = grub_le_to_cpu32 (index_size); node->compress_index = grub_malloc (node->compress_index_size * sizeof (node->compress_index[0])); if (!node->compress_index) { node->compressed = 0; grub_free (attr_node); return grub_errno; } if (grub_hfsplus_read_file (node, 0, 0, 0x104 + sizeof (index_size), node->compress_index_size * sizeof (node->compress_index[0]), (char *) node->compress_index) != (grub_ssize_t) (node->compress_index_size * sizeof (node->compress_index[0]))) { node->compressed = 0; grub_free (attr_node); grub_free (node->compress_index); grub_errno = 0; return 0; } node->cbuf_block = -1; node->cbuf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE); grub_free (attr_node); if (!node->cbuf) { node->compressed = 0; grub_free (node->compress_index); return grub_errno; } return 0; } if (cmp_head->type != HFSPLUS_COMPRESSION_INLINE) { grub_free (attr_node); return 0; } node->cbuf = grub_malloc (node->size); if (!node->cbuf) return grub_errno; if (grub_zlib_decompress ((char *) (cmp_head + 1), grub_cpu_to_be64 (attr_head->size) - sizeof (*cmp_head), 0, node->cbuf, node->size) < 0) return grub_errno; node->compressed = 1; return 0; }
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; }