grub_err_t grub_net_recv_udp_packet (struct grub_net_buff * nb, struct grub_net_network_level_interface * inf) { struct udphdr *udph; grub_net_socket_t sock; grub_err_t err; udph = (struct udphdr *) nb->data; err = grub_netbuff_pull (nb, sizeof (*udph)); if (err) return err; FOR_NET_SOCKETS (sock) { if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port && inf == sock->x_inf && sock->recv_hook) { if (sock->x_status == GRUB_NET_SOCKET_START) { sock->x_out_port = grub_be_to_cpu16 (udph->src); sock->x_status = GRUB_NET_SOCKET_ESTABLISHED; } /* App protocol remove its own reader. */ sock->recv_hook (sock, nb, sock->recv_hook_data); return GRUB_ERR_NONE; } } grub_netbuff_free (nb); return GRUB_ERR_NONE; }
static int grub_hfsplus_cmp_attrkey (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb) { struct grub_hfsplus_attrkey *attrkey_a = &keya->attrkey; struct grub_hfsplus_attrkey_internal *attrkey_b = &keyb->attrkey; grub_uint32_t aparent = grub_be_to_cpu32 (attrkey_a->cnid); grub_size_t len; int diff; if (aparent > attrkey_b->cnid) return 1; if (aparent < attrkey_b->cnid) return -1; len = grub_be_to_cpu16 (attrkey_a->namelen); if (len > attrkey_b->namelen) len = attrkey_b->namelen; /* Since it's big-endian memcmp gives the same result as manually comparing uint16_t but may be faster. */ diff = grub_memcmp (attrkey_a->name, attrkey_b->name, len * sizeof (attrkey_a->name[0])); if (diff == 0) diff = grub_be_to_cpu16 (attrkey_a->namelen) - attrkey_b->namelen; return diff; }
static grub_err_t sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { grub_partition_t p; struct grub_disk raw; struct grub_sun_block block; int partnum; raw = *disk; raw.partition = 0; p = (grub_partition_t) grub_malloc (sizeof (struct grub_partition)); if (! p) return grub_errno; p->offset = 0; p->data = 0; p->partmap = &grub_sun_partition_map; if (grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block), (char *) &block) == GRUB_ERR_NONE) { if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) 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_MAX_PARTS; partnum++) { struct grub_sun_partition_descriptor *desc; if (block.infos[partnum].id == 0 || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) continue; desc = &block.partitions[partnum]; p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); p->len = grub_be_to_cpu32 (desc->num_sectors); p->index = partnum; if (p->len) { if (hook (disk, p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } } grub_free (p); return grub_errno; }
static int cmp (const void *a__, const void *b__) { struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; struct tftphdr *a = (struct tftphdr *) a_->data; struct tftphdr *b = (struct tftphdr *) b_->data; /* We want the first elements to be on top. */ return -cmp_block (grub_be_to_cpu16 (a->u.data.block), grub_be_to_cpu16 (b->u.data.block)); }
/* Compare the K1 and K2 extent overflow file keys. */ static int grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, struct grub_hfs_extent_key *k2) { int cmp = k1->forktype - k2->forktype; if (cmp == 0) cmp = grub_be_to_cpu32 (k1->fileid) - grub_be_to_cpu32 (k2->fileid); if (cmp == 0) cmp = (grub_be_to_cpu16 (k1->first_block) - grub_be_to_cpu16 (k2->first_block)); return cmp; }
static struct grub_hfsplus_data * grub_hfsplus_mount (grub_disk_t disk) { struct grub_hfsplus_data *data; struct grub_hfsplus_btheader header; struct grub_hfsplus_btnode node; grub_uint16_t magic; union { struct grub_hfs_sblock hfs; struct grub_hfsplus_volheader hfsplus; } volheader; data = grub_malloc (sizeof (*data)); if (!data) return 0; data->disk = disk; /* Read the bootblock. */ grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader), &volheader); if (grub_errno) goto fail; data->embedded_offset = 0; if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC) { grub_disk_addr_t extent_start; grub_disk_addr_t ablk_size; grub_disk_addr_t ablk_start; /* See if there's an embedded HFS+ filesystem. */ if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC) { grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem"); goto fail; } /* Calculate the offset needed to translate HFS+ sector numbers. */ extent_start = grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block); ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz); ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block); data->embedded_offset = (ablk_start + extent_start * (ablk_size >> GRUB_DISK_SECTOR_BITS)); grub_disk_read (disk, data->embedded_offset + GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader), &volheader); if (grub_errno) goto fail; }
static grub_err_t grub_ext2_uuid (grub_device_t device, char **uuid) { struct grub_ext2_data *data; grub_disk_t disk = device->disk; grub_dl_ref (my_mod); data = grub_ext2_mount (disk); if (data) { *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]), grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]), grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]), grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7])); } else *uuid = NULL; grub_dl_unref (my_mod); grub_free (data); return grub_errno; }
static grub_err_t sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; struct grub_sun_block block; int partnum; grub_err_t err; p.partmap = &grub_sun_partition_map; err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), &block); if (err) return err; if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) 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_MAX_PARTS; partnum++) { struct grub_sun_partition_descriptor *desc; if (block.infos[partnum].id == 0 || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) continue; desc = &block.partitions[partnum]; p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); p.len = grub_be_to_cpu32 (desc->num_sectors); p.number = p.index = partnum; if (p.len) { if (hook (disk, &p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } return grub_errno; }
/* Read a 16-bit big-endian integer from FILE, convert it to native byte order, and store it in *VALUE. Returns 0 on success, 1 on failure. */ static int read_be_uint16 (grub_file_t file, grub_uint16_t * value) { if (grub_file_read (file, value, 2) != 2) return 1; *value = grub_be_to_cpu16 (*value); return 0; }
/* Return the offset of the record with the index INDEX, in the node NODE which is part of the B+ tree BTREE. */ static inline grub_off_t grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { char *cnode = (char *) node; void *recptr; recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); }
/* Return the offset of the record with the index INDEX, in the node NODE which is part of the B+ tree BTREE. */ static inline unsigned int grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { char *cnode = (char *) node; grub_uint16_t *recptr; recptr = (grub_uint16_t *) (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); return grub_be_to_cpu16 (*recptr); }
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; }
static char * grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; grub_uint16_t t[MAX_NAMELEN / 2 + 1]; p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) return NULL; for (i=0; i<len; i++) t[i] = grub_be_to_cpu16 (grub_get_unaligned16 (us + 2 * i)); *grub_utf16_to_utf8 ((grub_uint8_t *) p, t, len) = '\0'; return p; }
/* Read the contents of the current section as a 16-bit integer value, which is stored into *VALUE. Returns 0 upon success, nonzero upon failure. */ static int read_section_as_short (struct font_file_section *section, grub_int16_t * value) { grub_uint16_t raw_value; if (section->length != 2) { grub_error (GRUB_ERR_BAD_FONT, "font file format error: section %c%c%c%c length " "is %d but should be 2", section->name[0], section->name[1], section->name[2], section->name[3], section->length); return 1; } if (grub_file_read (section->file, &raw_value, 2) != 2) return 1; *value = grub_be_to_cpu16 (raw_value); return 0; }
/* Lookup the extent starting with BLOCK in the filesystem described by DATA. Return the extent size in SIZE and the following extent in NEXTEXT. */ static grub_err_t grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block, int *size, int *nextext) { char *treeblock; struct grub_sfs_btree *tree; int i; int next; int prev; treeblock = grub_malloc (data->blocksize); if (!block) return 0; next = grub_be_to_cpu32 (data->rblock.btree); tree = (struct grub_sfs_btree *) treeblock; /* Handle this level in the btree. */ do { prev = 0; grub_disk_read (data->disk, next, 0, data->blocksize, treeblock); if (grub_errno) { grub_free (treeblock); return grub_errno; } for (i = 0; i < grub_be_to_cpu16 (tree->nodes); i++) { #define EXTNODE(tree, index) \ ((struct grub_sfs_btree_node *) (((char *) &(tree)->node[0]) \ + (index) * (tree)->nodesize)) /* Follow the tree down to the leaf level. */ if ((grub_be_to_cpu32 (EXTNODE(tree, i)->key) >= block) && !tree->leaf) { next = grub_be_to_cpu32 (EXTNODE (tree, i - 1)->data); break; } /* In case the last node is reached just use that one, it is the right match. */ if (i + 1 == grub_be_to_cpu16 (tree->nodes) && !tree->leaf) { next = grub_be_to_cpu32 (EXTNODE (tree, i)->data); break; } /* If the leaf level is reached, just find the correct extent. */ if (grub_be_to_cpu32 (EXTNODE (tree, i)->key) == block && tree->leaf) { struct grub_sfs_btree_extent *extent; extent = (struct grub_sfs_btree_extent *) EXTNODE (tree, i); /* We found a correct leaf. */ *size = grub_be_to_cpu16 (extent->size); *nextext = grub_be_to_cpu32 (extent->next); grub_free (treeblock); return 0; } #undef EXTNODE } } while (!tree->leaf); grub_free (treeblock); return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found"); }
/* 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) { 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; }
/* Find block BLOCK of the file FILE in the mounted UFS filesystem DATA. The first 3 extents are described by DAT. If cache is set, using caching to improve non-random reads. */ static unsigned int grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat, int file, int block, int cache) { grub_hfs_datarecord_t dr; int pos = 0; struct grub_hfs_extent_key key; int tree = 0; static int cache_file = 0; static int cache_pos = 0; static grub_hfs_datarecord_t cache_dr; grub_memcpy (dr, dat, sizeof (dr)); key.forktype = 0; key.fileid = grub_cpu_to_be32 (file); if (cache && cache_file == file && block > cache_pos) { pos = cache_pos; key.first_block = grub_cpu_to_be16 (pos); grub_memcpy (dr, cache_dr, sizeof (cache_dr)); } for (;;) { int i; /* Try all 3 extents. */ for (i = 0; i < 3; i++) { /* Check if the block is stored in this extent. */ if (grub_be_to_cpu16 (dr[i].count) + pos > block) { int first = grub_be_to_cpu16 (dr[i].first_block); /* If the cache is enabled, store the current position in the tree. */ if (tree && cache) { cache_file = file; cache_pos = pos; grub_memcpy (cache_dr, dr, sizeof (cache_dr)); } return (grub_be_to_cpu16 (data->sblock.first_block) + (first + block - pos) * GRUB_HFS_BLKS); } /* Try the next extent. */ pos += grub_be_to_cpu16 (dr[i].count); } /* Lookup the block in the extent overflow file. */ key.first_block = grub_cpu_to_be16 (pos); tree = 1; grub_hfs_find_node (data, (char *) &key, data->ext_root, 1, (char *) &dr, sizeof (dr)); if (grub_errno) return 0; } }
grub_err_t grub_net_arp_receive (struct grub_net_buff *nb, struct grub_net_card *card) { struct arphdr *arp_header = (struct arphdr *) nb->data; grub_uint8_t *sender_hardware_address; grub_uint8_t *target_hardware_address; grub_net_network_level_address_t sender_addr, target_addr; grub_net_link_level_address_t sender_hw_addr; struct grub_net_network_level_interface *inf; grub_uint8_t *sender_protocol_address, *target_protocol_address; sender_hardware_address = (grub_uint8_t *) arp_header + sizeof (*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP && arp_header->pln == 4) { sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); if (grub_memcmp (sender_protocol_address, &pending_req, 4) == 0) have_pending = 1; } else return GRUB_ERR_NONE; sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; grub_memcpy (sender_hw_addr.mac, sender_hardware_address, sizeof (sender_hw_addr.mac)); grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { /* Am I the protocol address target? */ if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) { grub_net_link_level_address_t target; /* We've already checked that pln is either 4 or 16. */ char tmp[arp_header->pln]; target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; grub_memcpy (target.mac, sender_hardware_address, 6); grub_memcpy (target_hardware_address, target.mac, 6); grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); grub_memcpy (tmp, sender_protocol_address, arp_header->pln); grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); grub_memcpy (target_protocol_address, tmp, arp_header->pln); /* Change operation to REPLY and send packet */ arp_header->op = grub_be_to_cpu16 (ARP_REPLY); send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP); } } return GRUB_ERR_NONE; }
static grub_err_t apple_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition part; struct grub_apple_header aheader; struct grub_apple_part apart; struct grub_disk raw; int partno = 0; unsigned pos = GRUB_DISK_SECTOR_SIZE; /* Enforce raw disk access. */ raw = *disk; raw.partition = 0; part.partmap = &grub_apple_partition_map; if (grub_disk_read (&raw, 0, 0, sizeof (aheader), (char *) &aheader)) return grub_errno; if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC) { grub_dprintf ("partition", "bad magic (found 0x%x; wanted 0x%x\n", grub_be_to_cpu16 (aheader.magic), GRUB_APPLE_HEADER_MAGIC); goto fail; } for (;;) { if (grub_disk_read (&raw, pos / GRUB_DISK_SECTOR_SIZE, pos % GRUB_DISK_SECTOR_SIZE, sizeof (struct grub_apple_part), (char *) &apart)) return grub_errno; if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC) { grub_dprintf ("partition", "partition %d: bad magic (found 0x%x; wanted 0x%x\n", partno, grub_be_to_cpu16 (apart.magic), GRUB_APPLE_PART_MAGIC); break; } part.start = grub_be_to_cpu32 (apart.first_phys_block); part.len = grub_be_to_cpu32 (apart.blockcnt); part.offset = pos; part.index = partno; grub_dprintf ("partition", "partition %d: name %s, type %s, start 0x%x, len 0x%x\n", partno, apart.partname, apart.parttype, grub_be_to_cpu32 (apart.first_phys_block), grub_be_to_cpu32 (apart.blockcnt)); if (hook (disk, &part)) return grub_errno; if (grub_be_to_cpu32 (apart.first_phys_block) == GRUB_DISK_SECTOR_SIZE * 2) return 0; pos += sizeof (struct grub_apple_part); partno++; } if (pos != GRUB_DISK_SECTOR_SIZE) return 0; fail: return grub_error (GRUB_ERR_BAD_PART_TABLE, "Apple partition map not found."); }
static grub_err_t apple_partition_map_iterate (grub_disk_t disk, grub_partition_iterate_hook_t hook, void *hook_data) { struct grub_partition part; struct grub_apple_header aheader; struct grub_apple_part apart; int partno = 0, partnum = 0; unsigned pos; part.partmap = &grub_apple_partition_map; if (grub_disk_read (disk, 0, 0, sizeof (aheader), &aheader)) return grub_errno; if (grub_be_to_cpu16 (aheader.magic) != GRUB_APPLE_HEADER_MAGIC) { grub_dprintf ("partition", "bad magic (found 0x%x; wanted 0x%x)\n", grub_be_to_cpu16 (aheader.magic), GRUB_APPLE_HEADER_MAGIC); goto fail; } pos = grub_be_to_cpu16 (aheader.blocksize); do { part.offset = pos / GRUB_DISK_SECTOR_SIZE; part.index = pos % GRUB_DISK_SECTOR_SIZE; if (grub_disk_read (disk, part.offset, part.index, sizeof (struct grub_apple_part), &apart)) return grub_errno; if (grub_be_to_cpu16 (apart.magic) != GRUB_APPLE_PART_MAGIC) { grub_dprintf ("partition", "partition %d: bad magic (found 0x%x; wanted 0x%x)\n", partno, grub_be_to_cpu16 (apart.magic), GRUB_APPLE_PART_MAGIC); break; } if (partnum == 0) partnum = grub_be_to_cpu32 (apart.partmap_size); part.start = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.first_phys_block) * grub_be_to_cpu16 (aheader.blocksize)) / GRUB_DISK_SECTOR_SIZE; part.len = ((grub_disk_addr_t) grub_be_to_cpu32 (apart.blockcnt) * grub_be_to_cpu16 (aheader.blocksize)) / GRUB_DISK_SECTOR_SIZE; part.offset = pos; part.index = partno; part.number = partno; grub_dprintf ("partition", "partition %d: name %s, type %s, start 0x%x, len 0x%x\n", partno, apart.partname, apart.parttype, grub_be_to_cpu32 (apart.first_phys_block), grub_be_to_cpu32 (apart.blockcnt)); if (hook (disk, &part, hook_data)) return grub_errno; pos += grub_be_to_cpu16 (aheader.blocksize); partno++; } while (partno < partnum); if (partno != 0) return 0; fail: return grub_error (GRUB_ERR_BAD_PART_TABLE, "Apple partition map not found"); }
extent_start = grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block); ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz); ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block); data->embedded_offset = (ablk_start + extent_start * (ablk_size >> GRUB_DISK_SECTOR_BITS)); grub_disk_read (disk, data->embedded_offset + GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader), &volheader); if (grub_errno) goto fail; } /* Make sure this is an HFS+ filesystem. XXX: Do we really support HFX? */ magic = grub_be_to_cpu16 (volheader.hfsplus.magic); if (((magic != GRUB_HFSPLUS_MAGIC) && (magic != GRUB_HFSPLUSX_MAGIC)) || volheader.hfsplus.blksize == 0 || ((volheader.hfsplus.blksize & (volheader.hfsplus.blksize - 1)) != 0) || grub_be_to_cpu32 (volheader.hfsplus.blksize) < GRUB_DISK_SECTOR_SIZE) { grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem"); goto fail; } grub_memcpy (&data->volheader, &volheader.hfsplus, sizeof (volheader.hfsplus)); for (data->log2blksize = 0; (1U << data->log2blksize) < grub_be_to_cpu32 (data->volheader.blksize); data->log2blksize++);
static grub_err_t tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, void *f) { grub_file_t file = f; struct tftphdr *tftph = (void *) nb->data; tftp_data_t data = file->data; grub_err_t err; grub_uint8_t *ptr; if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode)) { grub_dprintf ("tftp", "TFTP packet too small\n"); return GRUB_ERR_NONE; } tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: data->block_size = TFTP_DEFAULTSIZE_PACKET; data->have_oack = 1; for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0") - 1, 0, 0); if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0") - 1, 0, 0); while (ptr < nb->tail && *ptr) ptr++; ptr++; } data->block = 0; grub_netbuff_free (nb); err = ack (data, 0); grub_error_save (&data->save_err); return GRUB_ERR_NONE; case TFTP_DATA: if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode) + sizeof (tftph->u.data.block))) { grub_dprintf ("tftp", "TFTP packet too small\n"); return GRUB_ERR_NONE; } err = grub_priority_queue_push (data->pq, &nb); if (err) return err; { struct grub_net_buff **nb_top_p, *nb_top; while (1) { nb_top_p = grub_priority_queue_top (data->pq); if (!nb_top_p) return GRUB_ERR_NONE; nb_top = *nb_top_p; tftph = (struct tftphdr *) nb_top->data; if (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) >= 0) break; ack (data, grub_be_to_cpu16 (tftph->u.data.block)); grub_netbuff_free (nb_top); grub_priority_queue_pop (data->pq); } while (cmp_block (grub_be_to_cpu16 (tftph->u.data.block), data->block + 1) == 0) { unsigned size; grub_priority_queue_pop (data->pq); if (file->device->net->packs.count < 50) err = ack (data, data->block + 1); else { file->device->net->stall = 1; err = 0; } if (err) return err; err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); if (err) return err; size = nb_top->tail - nb_top->data; data->block++; if (size < data->block_size) { if (data->ack_sent < data->block) ack (data, data->block); file->device->net->eof = 1; file->device->net->stall = 1; grub_net_udp_close (data->sock); data->sock = NULL; } /* Prevent garbage in broken cards. Is it still necessary given that IP implementation has been fixed? */ if (size > data->block_size) { err = grub_netbuff_unput (nb_top, size - data->block_size); if (err) return err; } /* If there is data, puts packet in socket list. */ if ((nb_top->tail - nb_top->data) > 0) grub_net_put_packet (&file->device->net->packs, nb_top); else grub_netbuff_free (nb_top); } } return GRUB_ERR_NONE; case TFTP_ERROR: data->have_oack = 1; grub_netbuff_free (nb); grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); grub_error_save (&data->save_err); return GRUB_ERR_NONE; default: grub_netbuff_free (nb); return GRUB_ERR_NONE; } }
static struct grub_diskfilter_vg * make_vg (grub_disk_t disk, const struct grub_ldm_label *label) { grub_disk_addr_t startsec, endsec, cursec; struct grub_diskfilter_vg *vg; grub_err_t err; /* First time we see this volume group. We've to create the whole volume group structure. */ vg = grub_malloc (sizeof (*vg)); if (! vg) return NULL; vg->extent_size = 1; vg->name = grub_malloc (LDM_NAME_STRLEN + 1); vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1); if (! vg->uuid || !vg->name) { grub_free (vg->uuid); grub_free (vg->name); return NULL; } grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN); grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN); vg->name[LDM_NAME_STRLEN] = 0; vg->uuid[LDM_GUID_STRLEN] = 0; vg->uuid_len = grub_strlen (vg->uuid); vg->lvs = NULL; vg->pvs = NULL; startsec = grub_be_to_cpu64 (label->config_start); endsec = startsec + grub_be_to_cpu64 (label->config_size); /* First find disks. */ for (cursec = startsec + 0x12; cursec < endsec; cursec++) { struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) goto fail2; for (i = 0; i < ARRAY_SIZE (vblk); i++) { struct grub_diskfilter_pv *pv; grub_uint8_t *ptr; if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, sizeof (vblk[i].magic)) != 0) continue; if (grub_be_to_cpu16 (vblk[i].update_status) != STATUS_CONSISTENT && grub_be_to_cpu16 (vblk[i].update_status) != STATUS_STILL_ACTIVE) continue; if (vblk[i].type != ENTRY_DISK) continue; pv = grub_zalloc (sizeof (*pv)); if (!pv) goto fail2; pv->disk = 0; ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (pv); goto fail2; } pv->internal_id = grub_malloc (ptr[0] + 2); if (!pv->internal_id) { grub_free (pv); goto fail2; } grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1); pv->internal_id[(grub_size_t) ptr[0] + 1] = 0; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (pv); goto fail2; } /* ptr = name. */ ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (pv); goto fail2; } pv->id.uuidlen = *ptr; pv->id.uuid = grub_malloc (pv->id.uuidlen + 1); grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen); pv->id.uuid[pv->id.uuidlen] = 0; pv->next = vg->pvs; vg->pvs = pv; } } /* Then find LVs. */ for (cursec = startsec + 0x12; cursec < endsec; cursec++) { struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) goto fail2; for (i = 0; i < ARRAY_SIZE (vblk); i++) { struct grub_diskfilter_lv *lv; grub_uint8_t *ptr; if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, sizeof (vblk[i].magic)) != 0) continue; if (grub_be_to_cpu16 (vblk[i].update_status) != STATUS_CONSISTENT && grub_be_to_cpu16 (vblk[i].update_status) != STATUS_STILL_ACTIVE) continue; if (vblk[i].type != ENTRY_VOLUME) continue; lv = grub_zalloc (sizeof (*lv)); if (!lv) goto fail2; lv->vg = vg; lv->segment_count = 1; lv->segment_alloc = 1; lv->visible = 1; lv->segments = grub_zalloc (sizeof (*lv->segments)); if (!lv->segments) goto fail2; lv->segments->start_extent = 0; lv->segments->type = GRUB_DISKFILTER_MIRROR; lv->segments->node_count = 0; lv->segments->node_alloc = 8; lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes) * lv->segments->node_alloc); if (!lv->segments->nodes) goto fail2; ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv); goto fail2; } lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); if (!lv->internal_id) { grub_free (lv); goto fail2; } grub_memcpy (lv->internal_id, ptr, ptr[0] + 1); lv->internal_id[ptr[0] + 1] = 0; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv); goto fail2; } lv->name = grub_malloc (*ptr + 1); if (!lv->name) { grub_free (lv->internal_id); grub_free (lv); goto fail2; } grub_memcpy (lv->name, ptr + 1, *ptr); lv->name[*ptr] = 0; lv->fullname = grub_xasprintf ("ldm/%s/%s", vg->uuid, lv->name); if (!lv->fullname) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } /* ptr = volume type. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } /* ptr = flags. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } /* Skip state, type, unknown, volume number, zeros, flags. */ ptr += 14 + 1 + 1 + 1 + 3 + 1; /* ptr = number of children. */ if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } /* Skip 2 more fields. */ ptr += 8 + 8; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1>= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv); goto fail2; } lv->size = read_int (ptr + 1, *ptr); lv->segments->extent_count = lv->size; lv->next = vg->lvs; vg->lvs = lv; } } /* Now the components. */ for (cursec = startsec + 0x12; cursec < endsec; cursec++) { struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) goto fail2; for (i = 0; i < ARRAY_SIZE (vblk); i++) { struct grub_diskfilter_lv *comp; struct grub_diskfilter_lv *lv; grub_uint8_t type; grub_uint8_t *ptr; if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, sizeof (vblk[i].magic)) != 0) continue; if (grub_be_to_cpu16 (vblk[i].update_status) != STATUS_CONSISTENT && grub_be_to_cpu16 (vblk[i].update_status) != STATUS_STILL_ACTIVE) continue; if (vblk[i].type != ENTRY_COMPONENT) continue; comp = grub_zalloc (sizeof (*comp)); if (!comp) goto fail2; comp->visible = 0; comp->name = 0; comp->fullname = 0; ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); if (!comp->internal_id) { grub_free (comp); goto fail2; } grub_memcpy (comp->internal_id, ptr, ptr[0] + 1); comp->internal_id[ptr[0] + 1] = 0; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } /* ptr = name. */ ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } /* ptr = state. */ ptr += *ptr + 1; type = *ptr++; /* skip zeros. */ ptr += 4; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } /* ptr = number of children. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } ptr += 8 + 8; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } for (lv = vg->lvs; lv; lv = lv->next) { if (lv->internal_id[0] == ptr[0] && grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0) break; } if (!lv) { grub_free (comp->internal_id); grub_free (comp); continue; } comp->size = lv->size; if (type == SPANNED) { comp->segment_alloc = 8; comp->segment_count = 0; comp->segments = grub_malloc (sizeof (*comp->segments) * comp->segment_alloc); if (!comp->segments) goto fail2; } else { comp->segment_alloc = 1; comp->segment_count = 1; comp->segments = grub_malloc (sizeof (*comp->segments)); if (!comp->segments) goto fail2; comp->segments->start_extent = 0; comp->segments->extent_count = lv->size; comp->segments->layout = 0; if (type == STRIPE) comp->segments->type = GRUB_DISKFILTER_STRIPED; else if (type == RAID5) { comp->segments->type = GRUB_DISKFILTER_RAID5; comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK; } else goto fail2; ptr += *ptr + 1; ptr++; if (!(vblk[i].flags & 0x10)) goto fail2; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } comp->segments->stripe_size = read_int (ptr + 1, *ptr); ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { grub_free (comp->internal_id); grub_free (comp); goto fail2; } comp->segments->node_count = read_int (ptr + 1, *ptr); comp->segments->node_alloc = comp->segments->node_count; comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes) * comp->segments->node_alloc); if (!lv->segments->nodes) goto fail2; } if (lv->segments->node_alloc == lv->segments->node_count) { void *t; lv->segments->node_alloc *= 2; t = grub_realloc (lv->segments->nodes, sizeof (*lv->segments->nodes) * lv->segments->node_alloc); if (!t) goto fail2; lv->segments->nodes = t; } lv->segments->nodes[lv->segments->node_count].pv = 0; lv->segments->nodes[lv->segments->node_count].start = 0; lv->segments->nodes[lv->segments->node_count++].lv = comp; comp->next = vg->lvs; vg->lvs = comp; } } /* Partitions. */ for (cursec = startsec + 0x12; cursec < endsec; cursec++) { struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) goto fail2; for (i = 0; i < ARRAY_SIZE (vblk); i++) { struct grub_diskfilter_lv *comp; struct grub_diskfilter_node part; grub_disk_addr_t start, size; grub_uint8_t *ptr; part.name = 0; if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, sizeof (vblk[i].magic)) != 0) continue; if (grub_be_to_cpu16 (vblk[i].update_status) != STATUS_CONSISTENT && grub_be_to_cpu16 (vblk[i].update_status) != STATUS_STILL_ACTIVE) continue; if (vblk[i].type != ENTRY_PARTITION) continue; part.lv = 0; part.pv = 0; ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } /* ID */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } /* ptr = name. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } /* skip zeros and logcommit id. */ ptr += 4 + 8; if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } part.start = read_int (ptr, 8); start = read_int (ptr + 8, 8); ptr += 16; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } size = read_int (ptr + 1, *ptr); ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } for (comp = vg->lvs; comp; comp = comp->next) if (comp->internal_id[0] == ptr[0] && grub_memcmp (ptr + 1, comp->internal_id + 1, comp->internal_id[0]) == 0) goto out; continue; out: if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } ptr += *ptr + 1; struct grub_diskfilter_pv *pv; for (pv = vg->pvs; pv; pv = pv->next) if (pv->internal_id[0] == ptr[0] && grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0) part.pv = pv; if (comp->segment_alloc == 1) { unsigned node_index; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } node_index = read_int (ptr + 1, *ptr); if (node_index < comp->segments->node_count) comp->segments->nodes[node_index] = part; } else { if (comp->segment_alloc == comp->segment_count) { void *t; comp->segment_alloc *= 2; t = grub_realloc (comp->segments, comp->segment_alloc * sizeof (*comp->segments)); if (!t) goto fail2; comp->segments = t; } comp->segments[comp->segment_count].start_extent = start; comp->segments[comp->segment_count].extent_count = size; comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED; comp->segments[comp->segment_count].node_count = 1; comp->segments[comp->segment_count].node_alloc = 1; comp->segments[comp->segment_count].nodes = grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes)); if (!comp->segments[comp->segment_count].nodes) goto fail2; comp->segments[comp->segment_count].nodes[0] = part; comp->segment_count++; } } } if (grub_diskfilter_vg_register (vg)) goto fail2; return vg; fail2: { struct grub_diskfilter_lv *lv, *next_lv; struct grub_diskfilter_pv *pv, *next_pv; for (lv = vg->lvs; lv; lv = next_lv) { unsigned i; for (i = 0; i < lv->segment_count; i++) grub_free (lv->segments[i].nodes); next_lv = lv->next; grub_free (lv->segments); grub_free (lv->internal_id); grub_free (lv->name); grub_free (lv->fullname); grub_free (lv); } for (pv = vg->pvs; pv; pv = next_pv) { next_pv = pv->next; grub_free (pv->id.uuid); grub_free (pv); } } grub_free (vg->uuid); grub_free (vg); return NULL; }
static struct grub_diskfilter_vg * grub_ldm_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) { grub_err_t err; struct grub_ldm_label label; struct grub_diskfilter_vg *vg; #ifdef GRUB_UTIL grub_util_info ("scanning %s for LDM", disk->name); #endif { int i; int has_ldm = msdos_has_ldm_partition (disk); for (i = 0; i < 3; i++) { grub_disk_addr_t sector = LDM_LABEL_SECTOR; switch (i) { case 0: if (!has_ldm) continue; sector = LDM_LABEL_SECTOR; break; case 1: /* LDM is never inside a partition. */ if (!has_ldm || disk->partition) continue; sector = grub_disk_get_size (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) continue; sector--; break; /* FIXME: try the third copy. */ case 2: sector = gpt_ldm_sector (disk); if (!sector) continue; break; } err = grub_disk_read (disk, sector, 0, sizeof(label), &label); if (err) return NULL; if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0 && grub_be_to_cpu16 (label.ver_major) == 0x02 && grub_be_to_cpu16 (label.ver_minor) >= 0x0b && grub_be_to_cpu16 (label.ver_minor) <= 0x0c) break; } /* Return if we didn't find a label. */ if (i == 3) { #ifdef GRUB_UTIL grub_util_info ("no LDM signature found"); #endif return NULL; } } id->uuid = grub_malloc (LDM_GUID_STRLEN + 1); if (!id->uuid) return NULL; grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN); id->uuid[LDM_GUID_STRLEN] = 0; id->uuidlen = grub_strlen ((char *) id->uuid); *start_sector = grub_be_to_cpu64 (label.pv_start); { grub_size_t s; for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++); vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid); if (! vg) vg = make_vg (disk, &label); } if (!vg) { grub_free (id->uuid); return NULL; } return vg; }