/* Go the string STR and return the number after STR. *P will point at the number. In case STR is not found, *P will be NULL and the return value will be 0. */ static grub_uint64_t grub_lvm_getvalue (char **p, const char *str) { *p = grub_strstr (*p, str); if (! *p) return 0; *p += grub_strlen (str); return grub_strtoull (*p, p, 10); }
static char * adjust_file (const char *in, grub_size_t len) { const char *comma, *ptr, *rest; char *ret, *outptr; int overhead = 0; int part = -1, subpart = -1; if (in[0] != '(') return grub_legacy_escape (in, len); for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' && *ptr != ','; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; comma = ptr; if (*comma != ',') return grub_legacy_escape (in, len); part = grub_strtoull (comma + 1, (char **) &rest, 0); if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') { subpart = rest[1] - 'a'; rest += 2; } for (ptr = rest; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; /* 35 is enough for any 2 numbers. */ ret = grub_malloc (ptr - in + overhead + 35); if (!ret) return NULL; outptr = ret; for (ptr = in; ptr < in + len && ptr <= comma; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } if (subpart != -1) grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); else grub_snprintf (outptr, 35, "%d", part + 1); while (*outptr) outptr++; for (ptr = rest; ptr < in + len; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } *outptr = 0; return ret; }
static grub_err_t grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { char * str; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "badram string required"); grub_dprintf ("badram", "executing badram\n"); str = args[0]; while (1) { struct grub_cmd_badram_closure c; /* Parse address and mask. */ c.badaddr = grub_strtoull (str, &str, 16); if (*str == ',') str++; c.badmask = grub_strtoull (str, &str, 16); if (*str == ',') str++; if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = 0; return GRUB_ERR_NONE; } /* When part of a page is tainted, we discard the whole of it. There's no point in providing sub-page chunks. */ c.badmask &= ~(CHUNK_SIZE - 1); grub_dprintf ("badram", "badram %llx:%llx\n", (unsigned long long) c.badaddr, (unsigned long long) c.badmask); grub_mmap_iterate (grub_cmd_badram_hook, &c); } }
unsigned long grub_strtoul (const char *str, char **end, int base) { unsigned long long num; num = grub_strtoull (str, end, base); if (num > ~0UL) { grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); return ~0UL; } return (unsigned long) num; }
unsigned long grub_strtoul (const char *str, char **end, int base) { unsigned long long num; num = grub_strtoull (str, end, base); #if GRUB_CPU_SIZEOF_LONG != 8 if (num > ~0UL) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); return ~0UL; } #endif return (unsigned long) num; }
grub_err_t strtou64_h(const char *str, U64 * value_ret) { U64 value; int base = 0; char *end; const char *last = str + grub_strlen(str) - 1; if (last < str) return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number"); if (grub_tolower(*last) == 'h') { base = 16; last--; if (last < str) return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number"); } value = grub_strtoull(str, &end, base); if (grub_errno != GRUB_ERR_NONE || end != (last + 1)) { return grub_error(GRUB_ERR_BAD_NUMBER, "Unrecognized number"); } else { *value_ret = value; return GRUB_ERR_NONE; } }
static grub_err_t parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, grub_off_t off, grub_size_t sz) { char *buf; char *ptr; int has_paddr = 0; if (grub_file_seek (elf->file, off) == (grub_off_t) -1) return grub_errno; buf = grub_malloc (sz); if (!buf) return grub_errno; if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz) { if (grub_errno) return grub_errno; return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), elf->file->name); } xi->has_xen_guest = 1; for (ptr = buf; ptr && ptr - buf < (grub_ssize_t) sz; ptr = grub_strchr (ptr, ','), (ptr ? ptr++ : 0)) { if (grub_strncmp (ptr, "PAE=no,", sizeof ("PAE=no,") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386; continue; } if (grub_strncmp (ptr, "PAE=yes,", sizeof ("PAE=yes,") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE; continue; } if (grub_strncmp (ptr, "PAE=yes[extended-cr3],", sizeof ("PAE=yes[extended-cr3],") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE; xi->extended_cr3 = 1; continue; } if (grub_strncmp (ptr, "PAE=bimodal,", sizeof ("PAE=bimodal,") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE; continue; } if (grub_strncmp (ptr, "PAE=bimodal[extended-cr3],", sizeof ("PAE=bimodal[extended-cr3],") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE; xi->extended_cr3 = 1; continue; } if (grub_strncmp (ptr, "PAE=yes,bimodal,", sizeof ("PAE=yes,bimodal,") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE; continue; } if (grub_strncmp (ptr, "PAE=yes[extended-cr3],bimodal,", sizeof ("PAE=yes[extended-cr3],bimodal,") - 1) == 0) { if (xi->arch != GRUB_XEN_FILE_I386 && xi->arch != GRUB_XEN_FILE_I386_PAE && xi->arch != GRUB_XEN_FILE_I386_PAE_BIMODE) continue; xi->arch = GRUB_XEN_FILE_I386_PAE_BIMODE; xi->extended_cr3 = 1; continue; } if (grub_strncmp (ptr, "VIRT_BASE=", sizeof ("VIRT_BASE=") - 1) == 0) { xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16); if (grub_errno) return grub_errno; continue; } if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0) { xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16); if (grub_errno) return grub_errno; continue; } if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0) { xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16); xi->has_hypercall_page = 1; if (grub_errno) return grub_errno; continue; } if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0) { xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16); has_paddr = 1; if (grub_errno) return grub_errno; continue; } } if (xi->has_hypercall_page) xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base; if (!has_paddr) xi->paddr_offset = xi->virt_base; return GRUB_ERR_NONE; }
static grub_err_t grub_fs_blocklist_open (grub_file_t file, const char *name) { char *p = (char *) name; unsigned num = 0; unsigned i; grub_disk_t disk = file->device->disk; struct grub_fs_block *blocks; /* First, count the number of blocks. */ do { num++; p = grub_strchr (p, ','); if (p) p++; } while (p); /* Allocate a block list. */ blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1)); if (! blocks) return 0; file->size = 0; p = (char *) name; if (! *p) { blocks[0].offset = 0; blocks[0].length = (disk->total_sectors == GRUB_ULONG_MAX) ? GRUB_ULONG_MAX : (disk->total_sectors << 9); file->size = blocks[0].length; } else for (i = 0; i < num; i++) { if (*p != '+') { blocks[i].offset = grub_strtoull (p, &p, 0); if (grub_errno != GRUB_ERR_NONE || *p != '+') { grub_error (GRUB_ERR_BAD_FILENAME, "invalid file name `%s'", name); goto fail; } } p++; blocks[i].length = grub_strtoul (p, &p, 0); if (grub_errno != GRUB_ERR_NONE || blocks[i].length == 0 || (*p && *p != ',' && ! grub_isspace (*p))) { grub_error (GRUB_ERR_BAD_FILENAME, "invalid file name `%s'", name); goto fail; } if (disk->total_sectors < blocks[i].offset + blocks[i].length) { grub_error (GRUB_ERR_BAD_FILENAME, "beyond the total sectors"); goto fail; } blocks[i].offset <<= GRUB_DISK_SECTOR_BITS; blocks[i].length <<= GRUB_DISK_SECTOR_BITS; file->size += blocks[i].length; p++; } file->data = blocks; return GRUB_ERR_NONE; fail: grub_free (blocks); return grub_errno; }
int iterate_env (struct grub_env_var *var) { char *guid, *attr, *name, *varname; struct efi_variable *efivar; int len = 0; int i; grub_uint64_t guidcomp; if (grub_memcmp (var->name, "EfiEmu.pnvram.", sizeof ("EfiEmu.pnvram.") - 1) != 0) return 0; guid = var->name + sizeof ("EfiEmu.pnvram.") - 1; attr = grub_strchr (guid, '.'); if (!attr) return 0; attr++; name = grub_strchr (attr, '.'); if (!name) return 0; name++; efivar = (struct efi_variable *) nvramptr; if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "too many NVRAM variables for reserved variable space." " Try increasing EfiEmu.pnvram.size"); return 1; } nvramptr += sizeof (struct efi_variable); efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16)); if (*guid != '-') return 0; guid++; efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); if (*guid != '-') return 0; guid++; efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); if (*guid != '-') return 0; guid++; guidcomp = grub_strtoull (guid, 0, 16); for (i = 0; i < 8; i++) efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff; efivar->attributes = grub_strtoull (attr, 0, 16); varname = grub_malloc (grub_strlen (name) + 1); if (! varname) return 1; if (unescape (name, varname, varname + grub_strlen (name) + 1, &len)) return 1; len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr, (nvramsize - (nvramptr - nvram)) / 2, (grub_uint8_t *) varname, len, NULL); nvramptr += 2 * len; *((grub_uint16_t *) nvramptr) = 0; nvramptr += 2; efivar->namelen = 2 * len + 2; if (unescape (var->value, nvramptr, nvram + nvramsize, &len)) { efivar->namelen = 0; return 1; } nvramptr += len; efivar->size = len; return 0; }
static grub_err_t parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) { char *end = ptr + len; while (end > ptr && *(end - 1) == '\r') end--; *end = 0; /* Trailing CRLF. */ if (data->in_chunk_len == 1) { data->in_chunk_len = 2; return GRUB_ERR_NONE; } if (data->in_chunk_len == 2) { data->chunk_rem = grub_strtoul (ptr, 0, 16); grub_errno = GRUB_ERR_NONE; if (data->chunk_rem == 0) { file->device->net->eof = 1; file->device->net->stall = 1; if (file->size == GRUB_FILE_SIZE_UNKNOWN) file->size = have_ahead (file); } data->in_chunk_len = 0; return GRUB_ERR_NONE; } if (ptr == end) { data->headers_recv = 1; if (data->chunked) data->in_chunk_len = 2; return GRUB_ERR_NONE; } if (!data->first_line_recv) { int code; if (grub_memcmp (ptr, "HTTP/1.1 ", sizeof ("HTTP/1.1 ") - 1) != 0) { data->errmsg = grub_strdup (_("unsupported HTTP response")); data->first_line_recv = 1; return GRUB_ERR_NONE; } ptr += sizeof ("HTTP/1.1 ") - 1; code = grub_strtoul (ptr, &ptr, 10); if (grub_errno) return grub_errno; switch (code) { case 200: case 206: break; case 404: data->err = GRUB_ERR_FILE_NOT_FOUND; data->errmsg = grub_xasprintf (_("file `%s' not found"), data->filename); return GRUB_ERR_NONE; default: data->err = GRUB_ERR_NET_UNKNOWN_ERROR; /* TRANSLATORS: GRUB HTTP code is pretty young. So even perfectly valid answers like 403 will trigger this very generic message. */ data->errmsg = grub_xasprintf (_("unsupported HTTP error %d: %s"), code, ptr); return GRUB_ERR_NONE; } data->first_line_recv = 1; return GRUB_ERR_NONE; } if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1) == 0 && !data->size_recv) { ptr += sizeof ("Content-Length: ") - 1; file->size = grub_strtoull (ptr, &ptr, 10); data->size_recv = 1; return GRUB_ERR_NONE; } if (grub_memcmp (ptr, "Transfer-Encoding: chunked", sizeof ("Transfer-Encoding: chunked") - 1) == 0) { data->chunked = 1; return GRUB_ERR_NONE; } return GRUB_ERR_NONE; }