static void read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length, void *closure) { struct read_blocklist_closure *c = closure; sector = ((sector - c->part_start) << GRUB_DISK_SECTOR_BITS) + offset; if ((c->num) && (c->blocks[c->num - 1].offset + c->blocks[c->num - 1].length == sector)) { c->blocks[c->num - 1].length += length; goto quit; } if ((c->num & (BLOCKLIST_INC_STEP - 1)) == 0) { c->blocks = grub_realloc (c->blocks, (c->num + BLOCKLIST_INC_STEP) * sizeof (struct grub_fs_block)); if (! c->blocks) return; } c->blocks[c->num].offset = sector; c->blocks[c->num].length = length; c->num++; quit: c->total_size += length; }
static char * grub_getline (void) { int i; char *line; char *tmp; char c; i = 0; line = grub_malloc (1 + i + sizeof('\0')); if (! line) return NULL; while (1) { c = grub_getkey (); if ((c == '\n') || (c == '\r')) break; line[i] = c; if (grub_isprint (c)) grub_putchar (c); i++; tmp = grub_realloc (line, 1 + i + sizeof('\0')); if (! tmp) { grub_free (line); return NULL; } line = tmp; } line[i] = '\0'; return line; }
grub_err_t grub_uitree_set_prop (grub_uitree_t node, const char *name, const char *value) { int ofs, len; grub_uiprop_t p, *ptr, next; ofs = grub_strlen (name) + 1; len = ofs + grub_strlen (value) + 1; next = 0; ptr = &node->prop; while (*ptr) { if (! grub_strcmp ((*ptr)->name, name)) { next = (*ptr)->next; break; } ptr = &((*ptr)->next); } p = grub_realloc (*ptr, sizeof (struct grub_uiprop) + len); if (! p) return grub_errno; *ptr = p; p->next = next; grub_strcpy (p->name, name); grub_strcpy (p->name + ofs, value); p->value = &p->name[ofs]; return grub_errno; }
char * grub_partition_get_name (const grub_partition_t partition) { char *out = 0; int curlen = 0; grub_partition_t part; for (part = partition; part; part = part->parent) { /* Even on 64-bit machines this buffer is enough to hold longest number. */ char buf[grub_strlen (part->partmap->name) + 25]; int strl; grub_snprintf (buf, sizeof (buf), "%s%d", part->partmap->name, part->number + 1); strl = grub_strlen (buf); if (curlen) { out = grub_realloc (out, curlen + strl + 2); grub_memcpy (out + strl + 1, out, curlen); out[curlen + 1 + strl] = 0; grub_memcpy (out, buf, strl); out[strl] = ','; curlen = curlen + 1 + strl; } else { curlen = strl; out = grub_strdup (buf); } } return out; }
/* Add a memory region to map*/ static grub_err_t grub_efiemu_add_to_mmap (grub_uint64_t start, grub_uint64_t size, grub_efi_memory_type_t type) { grub_uint64_t page_start, npages; /* Extend map if necessary*/ if (mmap_num >= mmap_reserved_size) { efiemu_mmap = (grub_efi_memory_descriptor_t *) grub_realloc (efiemu_mmap, (++mmap_reserved_size) * sizeof (grub_efi_memory_descriptor_t)); if (!efiemu_mmap) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "not enough space for memory map"); } /* Fill slot*/ page_start = start - (start % GRUB_EFIEMU_PAGESIZE); npages = (size + (start % GRUB_EFIEMU_PAGESIZE) + GRUB_EFIEMU_PAGESIZE - 1) / GRUB_EFIEMU_PAGESIZE; efiemu_mmap[mmap_num].physical_start = page_start; efiemu_mmap[mmap_num].virtual_start = page_start; efiemu_mmap[mmap_num].num_pages = npages; efiemu_mmap[mmap_num].type = type; mmap_num++; return GRUB_ERR_NONE; }
/* Helper for match_devices. */ static int match_devices_iter (const char *name, void *data) { struct match_devices_ctx *ctx = data; char **t; char *buffer; /* skip partitions if asked to. */ if (ctx->noparts && grub_strchr (name, ',')) return 0; buffer = grub_xasprintf ("(%s)", name); if (! buffer) return 1; grub_dprintf ("expand", "matching: %s\n", buffer); if (regexec (ctx->regexp, buffer, 0, 0, 0)) { grub_dprintf ("expand", "not matched\n"); grub_free (buffer); return 0; } t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2)); if (! t) { grub_free (buffer); return 1; } ctx->devs = t; ctx->devs[ctx->ndev++] = buffer; ctx->devs[ctx->ndev] = 0; return 0; }
char * grub_efi_get_filename (grub_efi_device_path_t *dp) { char *name = 0; while (1) { grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) break; else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) { grub_efi_file_path_device_path_t *fp; grub_efi_uint16_t len; char *p; grub_size_t size; if (name) { size = grub_strlen (name); name[size] = '/'; size++; } else size = 0; len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) / sizeof (grub_efi_char16_t)); p = grub_realloc (name, size + len * 4 + 1); if (! p) { grub_free (name); return 0; } name = p; fp = (grub_efi_file_path_device_path_t *) dp; *grub_utf16_to_utf8 ((grub_uint8_t *) name + size, fp->path_name, len) = '\0'; } dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); } if (name) { /* EFI breaks paths with backslashes. */ char *p; for (p = name; *p; p++) if (*p == '\\') *p = '/'; } return name; }
static inline void get_space(grub_size_t need) { need += out_used; if (need > out_size) { out_size = need * 2; out_buff = grub_realloc(out_buff, out_size*sizeof(char)); /* FIX ME! handle out_buff == 0. */ } }
/* Extend the symlink. */ static void add_part (struct iterate_dir_ctx *ctx, const char *part, int len2) { int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1); if (! ctx->symlink) return; grub_memcpy (ctx->symlink + size, part, len2); ctx->symlink[size + len2] = 0; }
void * PREFIX (realloc) (void *relocator, grub_size_t size) { char *playground; if (!relocator) return PREFIX (alloc) (size); playground = (char *) relocator - PRE_REGION_SIZE; playground = grub_realloc (playground, size + MAX_OVERHEAD); if (!playground) return 0; *(grub_size_t *) playground = size; return playground + PRE_REGION_SIZE; }
grub_err_t grub_net_add_dns_server (const struct grub_net_network_level_address *s) { if (dns_servers_alloc <= dns_nservers) { int na = dns_servers_alloc * 2; struct grub_net_network_level_address *ns; if (na < 8) na = 8; ns = grub_realloc (dns_servers, na * sizeof (ns[0])); if (!ns) return grub_errno; dns_servers_alloc = na; dns_servers = ns; } dns_servers[dns_nservers++] = *s; return GRUB_ERR_NONE; }
static grub_err_t save_ref (struct grub_btrfs_leaf_descriptor *desc, grub_disk_addr_t addr, unsigned i, unsigned m, int l) { desc->depth++; if (desc->allocated < desc->depth) { void *newdata; desc->allocated *= 2; newdata = grub_realloc (desc->data, sizeof (desc->data[0]) * desc->allocated); if (!newdata) return grub_errno; desc->data = newdata; } desc->data[desc->depth - 1].addr = addr; desc->data[desc->depth - 1].iter = i; desc->data[desc->depth - 1].maxiter = m; desc->data[desc->depth - 1].leaf = l; return GRUB_ERR_NONE; }
grub_err_t grub_video_fb_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { unsigned i; if (start + count > framebuffer.palette_size) { framebuffer.palette_size = start + count; framebuffer.palette = grub_realloc (framebuffer.palette, sizeof (framebuffer.palette[0]) * framebuffer.palette_size); if (!framebuffer.palette) { grub_video_fb_fini (); return grub_errno; } } for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++) framebuffer.palette[start + i] = palette_data[i]; return GRUB_ERR_NONE; }
/* * grub_ubootdisk_register(): * Called for each disk device enumerated as part of U-Boot initialization * code. */ grub_err_t grub_ubootdisk_register (struct device_info *newdev) { struct ubootdisk_data *d; #define STOR_TYPE(x) ((x) & 0x0ff0) switch (STOR_TYPE (newdev->type)) { case DT_STOR_IDE: case DT_STOR_SATA: case DT_STOR_SCSI: case DT_STOR_MMC: case DT_STOR_USB: /* hd */ if (hd_num == hd_max) { int new_num; new_num = (hd_max ? hd_max * 2 : 1); d = grub_realloc(hd_devices, sizeof (struct ubootdisk_data) * new_num); if (!d) return grub_errno; hd_devices = d; hd_max = new_num; } d = &hd_devices[hd_num]; hd_num++; break; default: return GRUB_ERR_BAD_DEVICE; break; } d->dev = newdev; d->cookie = newdev->cookie; d->opencount = 0; return 0; }
static grub_err_t http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, void *f) { grub_file_t file = f; http_data_t data = file->data; grub_err_t err; while (1) { char *ptr = (char *) nb->data; if ((!data->headers_recv || data->in_chunk_len) && data->current_line) { int have_line = 1; char *t; ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); if (ptr) ptr++; else { have_line = 0; ptr = (char *) nb->tail; } t = grub_realloc (data->current_line, data->current_line_len + (ptr - (char *) nb->data)); if (!t) { grub_netbuff_free (nb); grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return grub_errno; } data->current_line = t; grub_memcpy (data->current_line + data->current_line_len, nb->data, ptr - (char *) nb->data); data->current_line_len += ptr - (char *) nb->data; if (!have_line) { grub_netbuff_free (nb); return GRUB_ERR_NONE; } err = parse_line (file, data, data->current_line, data->current_line_len); grub_free (data->current_line); data->current_line = 0; data->current_line_len = 0; if (err) { grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } } while (ptr < (char *) nb->tail && (!data->headers_recv || data->in_chunk_len)) { char *ptr2; ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr); if (!ptr2) { data->current_line = grub_malloc ((char *) nb->tail - ptr); if (!data->current_line) { grub_netbuff_free (nb); grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return grub_errno; } data->current_line_len = (char *) nb->tail - ptr; grub_memcpy (data->current_line, ptr, data->current_line_len); grub_netbuff_free (nb); return GRUB_ERR_NONE; } err = parse_line (file, data, ptr, ptr2 - ptr); if (err) { grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } ptr = ptr2 + 1; } if (((char *) nb->tail - ptr) <= 0) { grub_netbuff_free (nb); return GRUB_ERR_NONE; } err = grub_netbuff_pull (nb, ptr - (char *) nb->data); if (err) { grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } if (!(data->chunked && (grub_ssize_t) data->chunk_rem < nb->tail - nb->data)) { grub_net_put_packet (&file->device->net->packs, nb); if (file->device->net->packs.count >= 20) file->device->net->stall = 1; if (file->device->net->packs.count >= 100) grub_net_tcp_stall (data->sock); if (data->chunked) data->chunk_rem -= nb->tail - nb->data; return GRUB_ERR_NONE; } if (data->chunk_rem) { struct grub_net_buff *nb2; nb2 = grub_netbuff_alloc (data->chunk_rem); if (!nb2) return grub_errno; grub_netbuff_put (nb2, data->chunk_rem); grub_memcpy (nb2->data, nb->data, data->chunk_rem); if (file->device->net->packs.count >= 20) { file->device->net->stall = 1; grub_net_tcp_stall (data->sock); } grub_net_put_packet (&file->device->net->packs, nb2); grub_netbuff_pull (nb, data->chunk_rem); } data->in_chunk_len = 1; } }
/* * Analyze the string to see how many parameters we need from the varargs list, * and what their types are. We will only accept string parameters if they * appear as a %l or %s format following an explicit parameter reference (e.g., * %p2%s). All other parameters are numbers. * * 'number' counts coarsely the number of pop's we see in the string, and * 'popcount' shows the highest parameter number in the string. We would like * to simply use the latter count, but if we are reading termcap strings, there * may be cases that we cannot see the explicit parameter numbers. */ static inline int analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) { grub_size_t len2; int i; int lastpop = -1; int len; int number = 0; const char *cp = string; static char dummy[] = ""; *popcount = 0; if (cp == 0) return 0; if ((len2 = grub_strlen(cp)) > fmt_size) { fmt_size = len2 + fmt_size + 2; if ((fmt_buff = grub_realloc(fmt_buff, fmt_size*sizeof(char))) == 0) return 0; } grub_memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM); while ((cp - string) < (int) len2) { if (*cp == '%') { cp++; cp = parse_format(cp, fmt_buff, &len); switch (*cp) { default: break; case 'd': /* FALLTHRU */ case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ if (lastpop <= 0) number++; lastpop = -1; break; case 'l': case 's': if (lastpop > 0) p_is_s[lastpop - 1] = dummy; ++number; break; case 'p': cp++; i = (UChar(*cp) - '0'); if (i >= 0 && i <= NUM_PARM) { lastpop = i; if (lastpop > *popcount) *popcount = lastpop; } break; case 'P': ++number; ++cp; break; case 'g': cp++; break; case '\'': cp += 2; lastpop = -1; break; case '{': cp++; while (isdigit(UChar(*cp))) { cp++; } break; case '+': case '-': case '*': case '/': case 'm': case 'A': case 'O': case '&': case '|': case '^': case '=': case '<': case '>': lastpop = -1; number += 2; break; case '!': case '~': lastpop = -1; ++number; break; case 'i': /* will add 1 to first (usually two) parameters */ break; } } if (*cp != '\0') cp++; } if (number > NUM_PARM) number = NUM_PARM; return number; }
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 int grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_iso9660_dir dirent; grub_off_t offset = 0; grub_off_t len; struct iterate_dir_ctx ctx; len = get_node_size (dir); for (; offset < len; offset += dirent.len) { ctx.symlink = 0; ctx.was_continue = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; /* The end of the block, skip to the next one. */ if (!dirent.len) { offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ; continue; } { char name[MAX_NAMELEN + 1]; int nameoffset = offset + sizeof (dirent); struct grub_fshelp_node *node; int sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2)); int sua_size = dirent.len - sua_off; sua_off += offset + dir->data->susp_skip; ctx.filename = 0; ctx.filename_alloc = 0; ctx.type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge && grub_iso9660_susp_iterate (dir, sua_off, sua_size, susp_iterate_dir, &ctx)) return 0; /* Read the name. */ if (read_node (dir, nameoffset, dirent.namelen, (char *) name)) return 0; node = grub_malloc (sizeof (struct grub_fshelp_node)); if (!node) return 0; node->alloc_dirents = ARRAY_SIZE (node->dirents); node->have_dirents = 1; /* Setup a new node. */ node->data = dir->data; node->have_symlink = 0; /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ if (ctx.type == GRUB_FSHELP_UNKNOWN) { if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) ctx.type = GRUB_FSHELP_DIR; else ctx.type = GRUB_FSHELP_REG; } /* . and .. */ if (!ctx.filename && dirent.namelen == 1 && name[0] == 0) ctx.filename = (char *) "."; if (!ctx.filename && dirent.namelen == 1 && name[0] == 1) ctx.filename = (char *) ".."; /* The filename was not stored in a rock ridge entry. Read it from the iso9660 filesystem. */ if (!dir->data->joliet && !ctx.filename) { char *ptr; name[dirent.namelen] = '\0'; ctx.filename = grub_strrchr (name, ';'); if (ctx.filename) *ctx.filename = '\0'; /* ISO9660 names are not case-preserving. */ ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE; for (ptr = name; *ptr; ptr++) *ptr = grub_tolower (*ptr); if (ptr != name && *(ptr - 1) == '.') *(ptr - 1) = 0; ctx.filename = name; } if (dir->data->joliet && !ctx.filename) { char *semicolon; ctx.filename = grub_iso9660_convert_string ((grub_uint8_t *) name, dirent.namelen >> 1); semicolon = grub_strrchr (ctx.filename, ';'); if (semicolon) *semicolon = '\0'; ctx.filename_alloc = 1; } node->dirents[0] = dirent; while (dirent.flags & FLAG_MORE_EXTENTS) { offset += dirent.len; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } if (node->have_dirents >= node->alloc_dirents) { struct grub_fshelp_node *new_node; node->alloc_dirents *= 2; new_node = grub_realloc (node, sizeof (struct grub_fshelp_node) + ((node->alloc_dirents - ARRAY_SIZE (node->dirents)) * sizeof (node->dirents[0]))); if (!new_node) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } node = new_node; } node->dirents[node->have_dirents++] = dirent; } if (ctx.symlink) { if ((node->alloc_dirents - node->have_dirents) * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) { struct grub_fshelp_node *new_node; new_node = grub_realloc (node, sizeof (struct grub_fshelp_node) + ((node->alloc_dirents - ARRAY_SIZE (node->dirents)) * sizeof (node->dirents[0])) + grub_strlen (ctx.symlink) + 1); if (!new_node) { if (ctx.filename_alloc) grub_free (ctx.filename); grub_free (node); return 0; } node = new_node; } node->have_symlink = 1; grub_strcpy (node->symlink + node->have_dirents * sizeof (node->dirents[0]) - sizeof (node->dirents), ctx.symlink); grub_free (ctx.symlink); ctx.symlink = 0; ctx.was_continue = 0; } if (hook (ctx.filename, ctx.type, node, hook_data)) { if (ctx.filename_alloc) grub_free (ctx.filename); return 1; } if (ctx.filename_alloc) grub_free (ctx.filename); } }
static grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry, void *_ctx) { struct iterate_dir_ctx *ctx = _ctx; /* The filename in the rock ridge entry. */ if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) { /* The flags are stored at the data position 0, here the filename type is stored. */ /* FIXME: Fix this slightly improper cast. */ if (entry->data[0] & GRUB_ISO9660_RR_DOT) ctx->filename = (char *) "."; else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) ctx->filename = (char *) ".."; else if (entry->len >= 5) { grub_size_t off = 0, csize = 1; char *old; csize = entry->len - 5; old = ctx->filename; if (ctx->filename_alloc) { off = grub_strlen (ctx->filename); ctx->filename = grub_realloc (ctx->filename, csize + off + 1); } else { off = 0; ctx->filename = grub_zalloc (csize + 1); } if (!ctx->filename) { ctx->filename = old; return grub_errno; } ctx->filename_alloc = 1; grub_memcpy (ctx->filename + off, (char *) &entry->data[1], csize); ctx->filename[off + csize] = '\0'; } } /* The mode information (st_mode). */ else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) { /* At position 0 of the PX record the st_mode information is stored (little-endian). */ grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8)) & GRUB_ISO9660_FSTYPE_MASK); switch (mode) { case GRUB_ISO9660_FSTYPE_DIR: ctx->type = GRUB_FSHELP_DIR; break; case GRUB_ISO9660_FSTYPE_REG: ctx->type = GRUB_FSHELP_REG; break; case GRUB_ISO9660_FSTYPE_SYMLINK: ctx->type = GRUB_FSHELP_SYMLINK; break; default: ctx->type = GRUB_FSHELP_UNKNOWN; } } else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) { unsigned int pos = 1; /* The symlink is not stored as a POSIX symlink, translate it. */ while (pos + sizeof (*entry) < entry->len) { /* The current position is the `Component Flag'. */ switch (entry->data[pos] & 30) { case 0: { /* The data on pos + 2 is the actual data, pos + 1 is the length. Both are part of the `Component Record'. */ if (ctx->symlink && !ctx->was_continue) add_part (ctx, "/", 1); add_part (ctx, (char *) &entry->data[pos + 2], entry->data[pos + 1]); ctx->was_continue = (entry->data[pos] & 1); break; } case 2: add_part (ctx, "./", 2); break; case 4: add_part (ctx, "../", 3); break; case 8: add_part (ctx, "/", 1); break; } /* In pos + 1 the length of the `Component Record' is stored. */ pos += entry->data[pos + 1] + 2; } /* Check if `grub_realloc' failed. */ if (grub_errno) return grub_errno; } return 0; }
static grub_err_t interactive (void) { const char *ps1 = "lua> "; const char *ps2 = "lua>> "; const char *prompt = ps1; char *line; char *chunk = NULL; size_t len; size_t oldlen = 0; int r; grub_printf ("%s", N_ ("Welcome to lua, press the escape key to exit.")); while ((line = grub_cmdline_get (prompt)) != NULL) { /* len = lenght of chunk + line + newline character */ len = oldlen + grub_strlen (line) + 1; chunk = grub_realloc (chunk, len + 1); grub_strcpy (chunk + oldlen , line); chunk[len - 1] = '\n'; chunk[len] = '\0'; grub_free (line); r = luaL_loadbuffer (state, chunk, len, "stdin"); if (!r) { /* No error: Execute this chunk and prepare to read another */ r = lua_pcall (state, 0, 0, 0); if (r) { handle_lua_error ("Lua"); grub_print_error (); } grub_free (chunk); chunk = NULL; len = 0; prompt = ps1; } else if (incomplete (state, r)) { /* Chunk is incomplete, try reading another line */ prompt = ps2; } else if (r == LUA_ERRSYNTAX) { handle_lua_error ("Lua"); grub_print_error (); /* This chunk is garbage, try starting another one */ grub_free (chunk); chunk = NULL; len = 0; prompt = ps1; } else { /* Handle errors other than syntax errors (out of memory, etc.) */ grub_free (chunk); handle_lua_error ("Lua parser failed"); return grub_errno; } oldlen = len; } grub_free (chunk); lua_gc (state, LUA_GCCOLLECT, 0); return grub_errno; }
/* Read a line from the file FILE. */ char * grub_file_getline (grub_file_t file) { char c; int pos = 0; int literal = 0; char *cmdline; int max_len = 64; /* Initially locate some space. */ cmdline = grub_malloc (max_len); if (! cmdline) return 0; while (1) { if (grub_file_read (file, &c, 1) != 1) break; /* Skip all carriage returns. */ if (c == '\r') continue; /* Replace tabs with spaces. */ if (c == '\t') c = ' '; /* The previous is a backslash, then... */ if (literal) { /* If it is a newline, replace it with a space and continue. */ if (c == '\n') { c = ' '; /* Go back to overwrite the backslash. */ if (pos > 0) pos--; } literal = 0; } if (c == '\\') literal = 1; if (pos == 0) { if (! grub_isspace (c)) cmdline[pos++] = c; } else { if (pos >= max_len) { char *old_cmdline = cmdline; max_len = max_len * 2; cmdline = grub_realloc (cmdline, max_len); if (! cmdline) { grub_free (old_cmdline); return 0; } } if (c == '\n') break; cmdline[pos++] = c; } } cmdline[pos] = '\0'; /* If the buffer is empty, don't return anything at all. */ if (pos == 0) { grub_free (cmdline); cmdline = 0; } return cmdline; }
static struct grub_biosdisk_data * get_drive_geom (int drive) { int i; struct grub_biosdisk_data *data = grub_biosdisk_geom; grub_uint64_t total_sectors = 0; unsigned long cylinders; int is_fb = 0; struct fb_mbr *m; for (i = 0; i < grub_biosdisk_num; i++, data++) if (data->drive == drive) return data; m = (struct fb_mbr *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; if (drive != cd_drive) { if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1, GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0) return 0; is_fb = ((m->fb_magic == FB_MAGIC_LONG) && (m->end_magic == 0xaa55)); } else is_fb = 0; if ((grub_biosdisk_num & (DISK_NUM_INC - 1)) == 0) { grub_biosdisk_geom = grub_realloc (grub_biosdisk_geom, (grub_biosdisk_num + DISK_NUM_INC) * sizeof (*data)); if (! grub_biosdisk_geom) return 0; } data = &grub_biosdisk_geom[grub_biosdisk_num++]; grub_memset (data, 0, sizeof (*data)); data->drive = drive; if (drive == cd_drive) { data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM; data->max_sectors = data->sectors = 32; data->total_sectors = GRUB_ULONG_MAX; /* TODO: get the correct size. */ return data; } if (drive & 0x80) { /* HDD */ int version; version = grub_biosdisk_check_int13_extensions (drive); if (version) { struct grub_biosdisk_drp *drp = (struct grub_biosdisk_drp *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 512); /* Clear out the DRP. */ grub_memset (drp, 0, sizeof (*drp)); drp->size = sizeof (*drp); if (! grub_biosdisk_get_diskinfo_int13_extensions (drive, drp)) { data->flags = GRUB_BIOSDISK_FLAG_LBA; if (drp->cylinders == 65535) total_sectors = GRUB_ULONG_MAX; else if (drp->total_sectors) total_sectors = drp->total_sectors; else /* Some buggy BIOSes doesn't return the total sectors correctly but returns zero. So if it is zero, compute it by C/H/S returned by the LBA BIOS call. */ total_sectors = drp->cylinders * drp->heads * drp->sectors; } } data->sectors = 63; data->heads = 255; cylinders = 0; grub_biosdisk_get_diskinfo_standard (drive, &cylinders, &data->heads, &data->sectors); } else { grub_uint16_t t; t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x18)); data->sectors = ((t > 0) && (t <= 63)) ? t : 18; t = *((grub_uint16_t *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 0x1a)); data->heads = ((t > 0) && (t <= 255)) ? t : 2; cylinders = 1024; } data->max_sectors = 63; if (is_fb) { grub_uint16_t ofs = m->lba; data->max_sectors = m->max_sec; if (data->max_sectors >= 0x80) { data->max_sectors &= 0x7f; data->flags &= ~GRUB_BIOSDISK_FLAG_LBA; } if (! (data->flags & GRUB_BIOSDISK_FLAG_LBA)) { grub_uint16_t lba; if (grub_biosdisk_rw_standard (0x02, drive, 0, 1, 1, 1, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) goto next; lba = m->end_magic; if (lba == 0xaa55) { if (m->fb_magic != FB_MAGIC_LONG) goto next; else lba = m->lba; } data->sectors = lba - ofs; if (grub_biosdisk_rw_standard (0x02, drive, 1, 0, 1, 1, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) goto next; lba = m->end_magic; if (lba == 0xaa55) goto next; data->heads = (lba - ofs) / data->sectors; } data->flags |= GRUB_BIOSDISK_FLAG_FB; } if ((data->flags & GRUB_BIOSDISK_FLAG_LBA) && (data->max_sectors == 63)) data->max_sectors = GRUB_BIOSDISK_MAX_SECTORS; next: cylinders *= data->heads * data->sectors; if (total_sectors < cylinders) total_sectors = cylinders; data->total_sectors = total_sectors; return data; }