diff --git a/src/boot/efi/bcd.c b/src/boot/efi/bcd.c index 3eaabdd538..11f2a81c10 100644 --- a/src/boot/efi/bcd.c +++ b/src/boot/efi/bcd.c @@ -7,9 +7,7 @@ # define TEST_STATIC #else /* Provide our own "EFI API" if we are running as a unit test. */ -# include -# include -# include +# include "efi-string.h" # include "string-util-fundamental.h" # define CHAR8 char @@ -19,8 +17,6 @@ # define UINT32 uint32_t # define UINT64 uint64_t # define UINTN size_t -# define strlena(s) strlen(s) -# define strncaseeqa(a, b, n) strncaseeq((a), (b), (n)) # define TEST_STATIC static #endif @@ -139,7 +135,7 @@ static const Key *get_subkey(const UINT8 *bcd, UINT32 bcd_len, UINT32 offset, co return NULL; for (UINT16 i = 0; i < subkey->n_entries; i++) { - if (!strncaseeqa(name, subkey->entries[i].name_hint, sizeof(subkey->entries[i].name_hint))) + if (!strncaseeq8((char *) name, (char *) subkey->entries[i].name_hint, sizeof(subkey->entries[i].name_hint))) continue; const Key *key = get_key(bcd, bcd_len, subkey->entries[i].key_offset, name); @@ -168,7 +164,7 @@ static const Key *get_key(const UINT8 *bcd, UINT32 bcd_len, UINT32 offset, const return NULL; if (*name) { - if (strncaseeqa(name, key->key_name, key->key_name_len) && strlena(name) == key->key_name_len) + if (strncaseeq8((char *) name, (char *) key->key_name, key->key_name_len) && strlen8((const char *) name) == key->key_name_len) name += key->key_name_len; else return NULL; @@ -213,7 +209,7 @@ static const KeyValue *get_key_value(const UINT8 *bcd, UINT32 bcd_len, const Key if (BAD_OFFSET(kv->data_offset, kv->data_size, bcd_len)) continue; - if (strncaseeqa(name, kv->name, kv->name_len) && strlena(name) == kv->name_len) + if (strncaseeq8((char *)name, (char *) kv->name, kv->name_len) && strlen8((const char *) name) == kv->name_len) return kv; } diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index c9ee403c67..71f1227923 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -149,11 +149,11 @@ static BOOLEAN line_edit( assert(line_in); - len = strlen_ptr(*line_in); + len = strlen16(*line_in); size = len + 1024; line = xnew(CHAR16, size); print = xnew(CHAR16, x_max + 1); - StrCpy(line, strempty(*line_in)); + strcpy16(line, strempty(*line_in)); for (;;) { EFI_STATUS err; @@ -162,7 +162,7 @@ static BOOLEAN line_edit( UINTN cursor_color = TEXT_ATTR_SWAP(COLOR_EDIT); j = MIN(len - first, x_max); - CopyMem(print, line + first, j * sizeof(CHAR16)); + memcpy(print, line + first, j * sizeof(CHAR16)); while (clear > 0 && j < x_max) { clear--; print[j++] = ' '; @@ -317,7 +317,7 @@ static BOOLEAN line_edit( case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN): case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */ case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */ - if (!streq(line, *line_in)) { + if (!streq16(line, *line_in)) { FreePool(*line_in); *line_in = TAKE_PTR(line); } @@ -418,11 +418,11 @@ static CHAR16 *update_timeout_efivar(UINT32 *t, BOOLEAN inc) { switch (*t) { case TIMEOUT_UNSET: - return xstrdup(L"Menu timeout defined by configuration file."); + return xstrdup16(u"Menu timeout defined by configuration file."); case TIMEOUT_MENU_FORCE: - return xstrdup(L"Timeout disabled, menu will always be shown."); + return xstrdup16(u"Timeout disabled, menu will always be shown."); case TIMEOUT_MENU_HIDDEN: - return xstrdup(L"Menu disabled. Hold down key at bootup to show menu."); + return xstrdup16(u"Menu disabled. Hold down key at bootup to show menu."); default: return xpool_print(L"Menu timeout set to %u s.", *t); } @@ -554,7 +554,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { Print(L" config entry: %" PRIuN L"/%" PRIuN L"\n", i + 1, config->entry_count); ps_string(L" id: %s\n", entry->id); ps_string(L" title: %s\n", entry->title); - ps_string(L" title show: %s\n", streq_ptr(entry->title, entry->title_show) ? NULL : entry->title_show); + ps_string(L" title show: %s\n", streq16(entry->title, entry->title_show) ? NULL : entry->title_show); ps_string(L" sort key: %s\n", entry->sort_key); ps_string(L" version: %s\n", entry->version); ps_string(L" machine-id: %s\n", entry->machine_id); @@ -662,7 +662,7 @@ static BOOLEAN menu_run( /* length of the longest entry */ line_width = 0; for (UINTN i = 0; i < config->entry_count; i++) - line_width = MAX(line_width, StrLen(config->entries[i]->title_show)); + line_width = MAX(line_width, strlen16(config->entries[i]->title_show)); line_width = MIN(line_width + 2 * entry_padding, x_max); /* offsets to center the entries on the screen */ @@ -686,7 +686,7 @@ static BOOLEAN menu_run( UINTN j, padding; lines[i] = xnew(CHAR16, line_width + 1); - padding = (line_width - MIN(StrLen(config->entries[i]->title_show), line_width)) / 2; + padding = (line_width - MIN(strlen16(config->entries[i]->title_show), line_width)) / 2; for (j = 0; j < padding; j++) lines[i][j] = ' '; @@ -750,7 +750,7 @@ static BOOLEAN menu_run( * input. Therefore, draw one less character then we could for the status message. * Note that the same does not apply for the separator line as it will never be drawn * on the last line. */ - UINTN len = StrnLen(status, x_max - 1); + UINTN len = strnlen16(status, x_max - 1); UINTN x = (x_max - len) / 2; status[len] = '\0'; print_at(0, y_status, COLOR_NORMAL, clearline + x_max - x); @@ -861,7 +861,7 @@ static BOOLEAN menu_run( case KEYPRESS(0, 0, 'H'): case KEYPRESS(0, 0, '?'): /* This must stay below 80 characters! Q/v/Ctrl+l/f deliberately not advertised. */ - status = xstrdup(L"(d)efault (t/T)timeout (e)dit (r/R)resolution (p)rint (h)elp"); + status = xstrdup16(u"(d)efault (t/T)timeout (e)dit (r/R)resolution (p)rint (h)elp"); break; case KEYPRESS(0, 0, 'Q'): @@ -873,13 +873,13 @@ static BOOLEAN menu_run( case KEYPRESS(0, 0, 'D'): if (config->idx_default_efivar != idx_highlight) { FreePool(config->entry_default_efivar); - config->entry_default_efivar = xstrdup(config->entries[idx_highlight]->id); + config->entry_default_efivar = xstrdup16(config->entries[idx_highlight]->id); config->idx_default_efivar = idx_highlight; - status = xstrdup(L"Default boot entry selected."); + status = xstrdup16(u"Default boot entry selected."); } else { config->entry_default_efivar = mfree(config->entry_default_efivar); config->idx_default_efivar = IDX_INVALID; - status = xstrdup(L"Default boot entry cleared."); + status = xstrdup16(u"Default boot entry cleared."); } config->use_saved_entry_efivar = FALSE; refresh = TRUE; @@ -1092,7 +1092,7 @@ static CHAR8 *line_get_key_value( return NULL; linelen = 0; - while (line[linelen] && !strchra((CHAR8 *) "\n\r", line[linelen])) + while (line[linelen] && !strchr8("\n\r", line[linelen])) linelen++; /* move pos to next line */ @@ -1108,13 +1108,13 @@ static CHAR8 *line_get_key_value( line[linelen] = '\0'; /* remove leading whitespace */ - while (strchra((CHAR8 *) " \t", *line)) { + while (strchr8(" \t", *line)) { line++; linelen--; } /* remove trailing whitespace */ - while (linelen > 0 && strchra((CHAR8 *) " \t", line[linelen - 1])) + while (linelen > 0 && strchr8(" \t", line[linelen - 1])) linelen--; line[linelen] = '\0'; @@ -1123,13 +1123,13 @@ static CHAR8 *line_get_key_value( /* split key/value */ value = line; - while (*value && !strchra(sep, *value)) + while (*value && !strchr8((char *) sep, *value)) value++; if (*value == '\0') continue; *value = '\0'; value++; - while (*value && strchra(sep, *value)) + while (*value && strchr8((char *) sep, *value)) value++; /* unquote */ @@ -1154,10 +1154,10 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) { assert(content); while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { - if (strcmpa((CHAR8 *)"timeout", key) == 0) { - if (strcmpa((CHAR8*) "menu-force", value) == 0) + if (streq8((char *) key, "timeout")) { + if (streq8((char *) value, "menu-force")) config->timeout_sec_config = TIMEOUT_MENU_FORCE; - else if (strcmpa((CHAR8*) "menu-hidden", value) == 0) + else if (streq8((char *) value, "menu-hidden")) config->timeout_sec_config = TIMEOUT_MENU_HIDDEN; else { _cleanup_freepool_ CHAR16 *s = NULL; @@ -1169,8 +1169,8 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) { continue; } - if (strcmpa((CHAR8 *)"default", key) == 0) { - if (value[0] == '@' && strcmpa((CHAR8 *)"@saved", value) != 0) { + if (streq8((char *) key, "default")) { + if (value[0] == '@' && !streq8((char *) value, "@saved")) { log_error_stall(L"Unsupported special entry identifier: %a", value); continue; } @@ -1179,47 +1179,47 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) { continue; } - if (strcmpa((CHAR8 *)"editor", key) == 0) { + if (streq8((char *) key, "editor")) { err = parse_boolean(value, &config->editor); if (EFI_ERROR(err)) log_error_stall(L"Error parsing 'editor' config option: %a", value); continue; } - if (strcmpa((CHAR8 *)"auto-entries", key) == 0) { + if (streq8((char *) key, "auto-entries")) { err = parse_boolean(value, &config->auto_entries); if (EFI_ERROR(err)) log_error_stall(L"Error parsing 'auto-entries' config option: %a", value); continue; } - if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) { + if (streq8((char *) key, "auto-firmware")) { err = parse_boolean(value, &config->auto_firmware); if (EFI_ERROR(err)) log_error_stall(L"Error parsing 'auto-firmware' config option: %a", value); continue; } - if (strcmpa((CHAR8 *)"beep", key) == 0) { + if (streq8((char *) key, "beep")) { err = parse_boolean(value, &config->beep); if (EFI_ERROR(err)) log_error_stall(L"Error parsing 'beep' config option: %a", value); continue; } - if (strcmpa((CHAR8 *)"reboot-for-bitlocker", key) == 0) { + if (streq8((char *) key, "reboot-for-bitlocker")) { err = parse_boolean(value, &config->reboot_for_bitlocker); if (EFI_ERROR(err)) log_error_stall(L"Error parsing 'reboot-for-bitlocker' config option: %a", value); continue; } - if (strcmpa((CHAR8 *)"console-mode", key) == 0) { - if (strcmpa((CHAR8 *)"auto", value) == 0) + if (streq8((char *) key, "console-mode")) { + if (streq8((char *) value, "auto")) config->console_mode = CONSOLE_MODE_AUTO; - else if (strcmpa((CHAR8 *)"max", value) == 0) + else if (streq8((char *) value, "max")) config->console_mode = CONSOLE_MODE_FIRMWARE_MAX; - else if (strcmpa((CHAR8 *)"keep", value) == 0) + else if (streq8((char *) value, "keep")) config->console_mode = CONSOLE_MODE_KEEP; else { _cleanup_freepool_ CHAR16 *s = NULL; @@ -1230,12 +1230,12 @@ static void config_defaults_load_from_file(Config *config, CHAR8 *content) { continue; } - if (strcmpa((CHAR8*) "random-seed-mode", key) == 0) { - if (strcmpa((CHAR8*) "off", value) == 0) + if (streq8((char *) key, "random-seed-mode")) { + if (streq8((char *) value, "off")) config->random_seed_mode = RANDOM_SEED_OFF; - else if (strcmpa((CHAR8*) "with-system-token", value) == 0) + else if (streq8((char *) value, "with-system-token")) config->random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN; - else if (strcmpa((CHAR8*) "always", value) == 0) + else if (streq8((char *) value, "always")) config->random_seed_mode = RANDOM_SEED_ALWAYS; else { BOOLEAN on; @@ -1277,13 +1277,13 @@ static void config_entry_parse_tries( * foobar+4-0.efi → foobar+3-1.efi → foobar+2-2.efi → foobar+1-3.efi → foobar+0-4.efi → STOP! */ - i = StrLen(file); + i = strlen16(file); /* Chop off any suffix such as ".conf" or ".efi" */ if (suffix) { UINTN suffix_length; - suffix_length = StrLen(suffix); + suffix_length = strlen16(suffix); if (i < suffix_length) return; @@ -1360,13 +1360,13 @@ good: entry->tries_left = left; entry->tries_done = done; - entry->path = xstrdup(path); - entry->current_name = xstrdup(file); + entry->path = xstrdup16(path); + entry->current_name = xstrdup16(file); next_left = left <= 0 ? 0 : left - 1; next_done = done >= (UINTN) -2 ? (UINTN) -2 : done + 1; - prefix = xstrdup(file); + prefix = xstrdup16(file); prefix[i] = 0; entry->next_name = xpool_print(L"%s+%" PRIuN L"-%" PRIuN L"%s", prefix, next_left, next_done, strempty(suffix)); @@ -1399,7 +1399,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { return; /* And rename the file */ - StrCpy(file_info->FileName, entry->next_name); + strcpy16(file_info->FileName, entry->next_name); err = handle->SetInfo(handle, &GenericFileInfo, file_info_size, file_info); if (EFI_ERROR(err)) { log_error_stall(L"Failed to rename '%s' to '%s', ignoring: %r", old_path, entry->next_name, err); @@ -1415,7 +1415,7 @@ static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) { efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, 0); /* If the file we just renamed is the loader path, then let's update that. */ - if (StrCmp(entry->loader, old_path) == 0) { + if (streq16(entry->loader, old_path)) { FreePool(entry->loader); entry->loader = TAKE_PTR(new_path); } @@ -1450,31 +1450,31 @@ static void config_entry_add_type1( }; while ((line = line_get_key_value(content, (CHAR8 *)" \t", &pos, &key, &value))) { - if (strcmpa((CHAR8 *)"title", key) == 0) { + if (streq8((char *) key, "title")) { FreePool(entry->title); entry->title = xstra_to_str(value); continue; } - if (strcmpa((CHAR8 *)"sort-key", key) == 0) { + if (streq8((char *) key, "sort-key")) { FreePool(entry->sort_key); entry->sort_key = xstra_to_str(value); continue; } - if (strcmpa((CHAR8 *)"version", key) == 0) { + if (streq8((char *) key, "version")) { FreePool(entry->version); entry->version = xstra_to_str(value); continue; } - if (strcmpa((CHAR8 *)"machine-id", key) == 0) { + if (streq8((char *) key, "machine-id")) { FreePool(entry->machine_id); entry->machine_id = xstra_to_str(value); continue; } - if (strcmpa((CHAR8 *)"linux", key) == 0) { + if (streq8((char *) key, "linux")) { FreePool(entry->loader); entry->type = LOADER_LINUX; entry->loader = xstra_to_path(value); @@ -1482,35 +1482,35 @@ static void config_entry_add_type1( continue; } - if (strcmpa((CHAR8 *)"efi", key) == 0) { + if (streq8((char *) key, "efi")) { entry->type = LOADER_EFI; FreePool(entry->loader); entry->loader = xstra_to_path(value); /* do not add an entry for ourselves */ - if (loaded_image_path && StriCmp(entry->loader, loaded_image_path) == 0) { + if (loaded_image_path && strcaseeq16(entry->loader, loaded_image_path)) { entry->type = LOADER_UNDEFINED; break; } continue; } - if (strcmpa((CHAR8 *)"architecture", key) == 0) { + if (streq8((char *) key, "architecture")) { /* do not add an entry for an EFI image of architecture not matching with that of the image */ - if (strcmpa((CHAR8 *)EFI_MACHINE_TYPE_NAME, value) != 0) { + if (!streq8((char *) value, EFI_MACHINE_TYPE_NAME)) { entry->type = LOADER_UNDEFINED; break; } continue; } - if (strcmpa((CHAR8 *)"devicetree", key) == 0) { + if (streq8((char *) key, "devicetree")) { FreePool(entry->devicetree); entry->devicetree = xstra_to_path(value); continue; } - if (strcmpa((CHAR8 *)"initrd", key) == 0) { + if (streq8((char *) key, "initrd")) { entry->initrd = xreallocate_pool( entry->initrd, n_initrd == 0 ? 0 : (n_initrd + 1) * sizeof(UINT16 *), @@ -1520,7 +1520,7 @@ static void config_entry_add_type1( continue; } - if (strcmpa((CHAR8 *)"options", key) == 0) { + if (streq8((char *) key, "options")) { _cleanup_freepool_ CHAR16 *new = NULL; new = xstra_to_str(value); @@ -1547,8 +1547,8 @@ static void config_entry_add_type1( return; entry->device = device; - entry->id = xstrdup(file); - StrLwr(entry->id); + entry->id = xstrdup16(file); + strtolower16(entry->id); config_add_entry(config, entry); @@ -1606,8 +1606,8 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { (void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &config->entry_default_efivar); - config->use_saved_entry = streq_ptr(config->entry_default_config, L"@saved"); - config->use_saved_entry_efivar = streq_ptr(config->entry_default_efivar, L"@saved"); + config->use_saved_entry = streq16(config->entry_default_config, L"@saved"); + config->use_saved_entry_efivar = streq16(config->entry_default_efivar, L"@saved"); if (config->use_saved_entry || config->use_saved_entry_efivar) (void) efivar_get(LOADER_GUID, L"LoaderEntryLastBooted", &config->entry_saved); } @@ -1656,8 +1656,8 @@ static void config_load_entries( } } -static INTN config_entry_compare(const ConfigEntry *a, const ConfigEntry *b) { - INTN r; +static int config_entry_compare(const ConfigEntry *a, const ConfigEntry *b) { + int r; assert(a); assert(b); @@ -1676,12 +1676,12 @@ static INTN config_entry_compare(const ConfigEntry *a, const ConfigEntry *b) { return r; if (a->sort_key && b->sort_key) { - r = strcmp(a->sort_key, b->sort_key); + r = strcmp16(a->sort_key, b->sort_key); if (r != 0) return r; /* If multiple installations of the same OS are around, group by machine ID */ - r = strcmp_ptr(a->machine_id, b->machine_id); + r = strcmp16(a->machine_id, b->machine_id); if (r != 0) return r; @@ -1773,7 +1773,7 @@ static BOOLEAN entries_unique(ConfigEntry **entries, BOOLEAN *unique, UINTN entr for (UINTN i = 0; i < entry_count; i++) for (UINTN k = i + 1; k < entry_count; k++) { - if (StrCmp(entries[i]->title_show, entries[k]->title_show) != 0) + if (!streq16(entries[i]->title_show, entries[k]->title_show)) continue; is_unique = unique[i] = unique[k] = FALSE; @@ -1792,7 +1792,7 @@ static void config_title_generate(Config *config) { for (UINTN i = 0; i < config->entry_count; i++) { assert(!config->entries[i]->title_show); unique[i] = TRUE; - config->entries[i]->title_show = xstrdup(config->entries[i]->title ?: config->entries[i]->id); + config->entries[i]->title_show = xstrdup16(config->entries[i]->title ?: config->entries[i]->id); } if (entries_unique(config->entries, unique, config->entry_count)) @@ -1829,7 +1829,7 @@ static void config_title_generate(Config *config) { config->entries[i]->title_show = xpool_print( L"%s (%.*s)", t, - StrnLen(config->entries[i]->machine_id, 8), + strnlen16(config->entries[i]->machine_id, 8), config->entries[i]->machine_id); } @@ -1866,7 +1866,7 @@ static BOOLEAN is_sd_boot(EFI_FILE *root_dir, const CHAR16 *loader_path) { if (EFI_ERROR(err) || size != read) return FALSE; - return CompareMem(content, magic, sizeof(magic)) == 0; + return memcmp(content, magic, sizeof(magic)) == 0; } static ConfigEntry *config_entry_add_loader_auto( @@ -1897,7 +1897,7 @@ static ConfigEntry *config_entry_add_loader_auto( * * If the default loader is not us, it might be shim. It would * chainload GRUBX64.EFI in that case, which might be us.*/ - if (StriCmp(loader, loaded_image_path) == 0 || + if (strcaseeq16(loader, loaded_image_path) || is_sd_boot(root_dir, loader) || is_sd_boot(root_dir, L"\\EFI\\BOOT\\GRUB" EFI_MACHINE_TYPE_NAME L".EFI")) return NULL; @@ -1911,11 +1911,11 @@ static ConfigEntry *config_entry_add_loader_auto( ConfigEntry *entry = xnew(ConfigEntry, 1); *entry = (ConfigEntry) { - .id = xstrdup(id), + .id = xstrdup16(id), .type = LOADER_AUTO, - .title = xstrdup(title), + .title = xstrdup16(title), .device = device, - .loader = xstrdup(loader), + .loader = xstrdup16(loader), .key = key, .tries_done = UINTN_MAX, .tries_left = UINTN_MAX, @@ -1986,7 +1986,7 @@ static EFI_STATUS boot_windows_bitlocker(void) { if (EFI_ERROR(err)) continue; - if (CompareMem(buf + 3, "-FVE-FS-", STRLEN("-FVE-FS-")) == 0) { + if (memcmp(buf + 3, "-FVE-FS-", STRLEN("-FVE-FS-")) == 0) { found = TRUE; break; } @@ -2021,7 +2021,7 @@ static EFI_STATUS boot_windows_bitlocker(void) { if (buf_size < offset + sizeof(CHAR16)) continue; - if (streq((CHAR16 *) (buf + offset), L"Windows Boot Manager")) { + if (streq16((CHAR16 *) (buf + offset), L"Windows Boot Manager")) { err = efivar_set_raw( EFI_GLOBAL_GUID, L"BootNext", @@ -2132,49 +2132,49 @@ static void config_entry_add_unified( /* read properties from the embedded os-release file */ while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) { - if (strcmpa((const CHAR8*) "PRETTY_NAME", key) == 0) { + if (streq8((char *) key, "PRETTY_NAME")) { FreePool(os_pretty_name); os_pretty_name = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "IMAGE_ID", key) == 0) { + if (streq8((char *) key, "IMAGE_ID")) { FreePool(os_image_id); os_image_id = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "NAME", key) == 0) { + if (streq8((char *) key, "NAME")) { FreePool(os_name); os_name = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "ID", key) == 0) { + if (streq8((char *) key, "ID")) { FreePool(os_id); os_id = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "IMAGE_VERSION", key) == 0) { + if (streq8((char *) key, "IMAGE_VERSION")) { FreePool(os_image_version); os_image_version = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "VERSION", key) == 0) { + if (streq8((char *) key, "VERSION")) { FreePool(os_version); os_version = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "VERSION_ID", key) == 0) { + if (streq8((char *) key, "VERSION_ID")) { FreePool(os_version_id); os_version_id = xstra_to_str(value); continue; } - if (strcmpa((const CHAR8*) "BUILD_ID", key) == 0) { + if (streq8((char *) key, "BUILD_ID")) { FreePool(os_build_id); os_build_id = xstra_to_str(value); continue; @@ -2197,19 +2197,19 @@ static void config_entry_add_unified( ConfigEntry *entry = xnew(ConfigEntry, 1); *entry = (ConfigEntry) { - .id = xstrdup(f->FileName), + .id = xstrdup16(f->FileName), .type = LOADER_UNIFIED_LINUX, - .title = xstrdup(good_name), - .version = good_version ? xstrdup(good_version) : NULL, + .title = xstrdup16(good_name), + .version = xstrdup16(good_version), .device = device, .loader = xpool_print(L"\\EFI\\Linux\\%s", f->FileName), - .sort_key = good_sort_key ? xstrdup(good_sort_key) : NULL, + .sort_key = xstrdup16(good_sort_key), .key = 'l', .tries_done = UINTN_MAX, .tries_left = UINTN_MAX, }; - StrLwr(entry->id); + strtolower16(entry->id); config_add_entry(config, entry); config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi"); @@ -2375,7 +2375,7 @@ static EFI_STATUS image_start( CHAR16 *options = options_initrd ?: entry->options; if (options) { loaded_image->LoadOptions = options; - loaded_image->LoadOptionsSize = StrSize(options); + loaded_image->LoadOptionsSize = strsize16(options); /* Try to log any options to the TPM, especially to catch manually edited options */ (void) tpm_log_load_options(options); @@ -2426,15 +2426,15 @@ static void config_write_entries_to_variable(Config *config) { assert(config); for (UINTN i = 0; i < config->entry_count; i++) - sz += StrSize(config->entries[i]->id); + sz += strsize16(config->entries[i]->id); p = buffer = xallocate_pool(sz); for (UINTN i = 0; i < config->entry_count; i++) { UINTN l; - l = StrSize(config->entries[i]->id); - CopyMem(p, config->entries[i]->id, l); + l = strsize16(config->entries[i]->id); + memcpy(p, config->entries[i]->id, l); p += l; } @@ -2454,12 +2454,12 @@ static void save_selected_entry(const Config *config, const ConfigEntry *entry) (void) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, 0); /* Do not save or delete if this was a oneshot boot. */ - if (streq_ptr(config->entry_oneshot, entry->id)) + if (streq16(config->entry_oneshot, entry->id)) return; if (config->use_saved_entry_efivar || (!config->entry_default_efivar && config->use_saved_entry)) { /* Avoid unnecessary NVRAM writes. */ - if (streq_ptr(config->entry_saved, entry->id)) + if (streq16(config->entry_saved, entry->id)) return; (void) efivar_set(LOADER_GUID, L"LoaderEntryLastBooted", entry->id, EFI_VARIABLE_NON_VOLATILE); @@ -2545,8 +2545,8 @@ static void config_load_all_entries( if (config->auto_firmware && FLAGS_SET(get_os_indications_supported(), EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) { ConfigEntry *entry = xnew(ConfigEntry, 1); *entry = (ConfigEntry) { - .id = xstrdup(L"auto-reboot-to-firmware-setup"), - .title = xstrdup(L"Reboot Into Firmware Interface"), + .id = xstrdup16(u"auto-reboot-to-firmware-setup"), + .title = xstrdup16(u"Reboot Into Firmware Interface"), .call = reboot_into_firmware, .tries_done = UINTN_MAX, .tries_left = UINTN_MAX, diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 14957130be..66ef5da313 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -81,12 +81,12 @@ static EFI_STATUS pack_cpio_one( l = 6 + 13*8 + 1 + 1; /* Fixed CPIO header size, slash separator, and NUL byte after the file name*/ - target_dir_prefix_size = strlena(target_dir_prefix); + target_dir_prefix_size = strlen8((const char *) target_dir_prefix); if (l > UINTN_MAX - target_dir_prefix_size) return EFI_OUT_OF_RESOURCES; l += target_dir_prefix_size; - fname_size = StrLen(fname); + fname_size = strlen16(fname); if (l > UINTN_MAX - fname_size) return EFI_OUT_OF_RESOURCES; l += fname_size; /* append space for file name */ @@ -116,7 +116,7 @@ static EFI_STATUS pack_cpio_one( *cpio_buffer = a; a = (CHAR8*) *cpio_buffer + *cpio_buffer_size; - CopyMem(a, "070701", 6); /* magic ID */ + memcpy(a, "070701", 6); /* magic ID */ a += 6; a = write_cpio_word(a, (*inode_counter)++); /* inode */ @@ -139,7 +139,7 @@ static EFI_STATUS pack_cpio_one( a = write_cpio_word(a, target_dir_prefix_size + fname_size + 2); /* fname size */ a = write_cpio_word(a, 0); /* "crc" */ - CopyMem(a, target_dir_prefix, target_dir_prefix_size); + memcpy(a, target_dir_prefix, target_dir_prefix_size); a += target_dir_prefix_size; *(a++) = '/'; a = mangle_filename(a, fname); @@ -147,7 +147,7 @@ static EFI_STATUS pack_cpio_one( /* Pad to next multiple of 4 */ a = pad4(a, *cpio_buffer); - CopyMem(a, contents, contents_size); + memcpy(a, contents, contents_size); a += contents_size; /* Pad to next multiple of 4 */ @@ -182,7 +182,7 @@ static EFI_STATUS pack_cpio_dir( l = 6 + 13*8 + 1; /* Fixed CPIO header size, and NUL byte after the file name*/ - path_size = strlena(path); + path_size = strlen8((const char *) path); if (l > UINTN_MAX - path_size) return EFI_OUT_OF_RESOURCES; l += path_size; @@ -198,7 +198,7 @@ static EFI_STATUS pack_cpio_dir( *cpio_buffer = a = xreallocate_pool(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l); a = (CHAR8*) *cpio_buffer + *cpio_buffer_size; - CopyMem(a, "070701", 6); /* magic ID */ + memcpy(a, "070701", 6); /* magic ID */ a += 6; a = write_cpio_word(a, (*inode_counter)++); /* inode */ @@ -215,7 +215,7 @@ static EFI_STATUS pack_cpio_dir( a = write_cpio_word(a, path_size + 1); /* fname size */ a = write_cpio_word(a, 0); /* "crc" */ - CopyMem(a, path, path_size + 1); + memcpy(a, path, path_size + 1); a += path_size + 1; /* Pad to next multiple of 4 */ @@ -248,14 +248,14 @@ static EFI_STATUS pack_cpio_prefix( for (const CHAR8 *p = path;;) { const CHAR8 *e; - e = strchra(p, '/'); + e = (const CHAR8 *) strchr8((const char *) p, '/'); if (!e) break; if (e > p) { _cleanup_freepool_ CHAR8 *t = NULL; - t = xstrndup8(path, e - path); + t = (CHAR8 *) xstrndup8((const char *) path, e - path); if (!t) return EFI_OUT_OF_RESOURCES; @@ -298,7 +298,7 @@ static EFI_STATUS pack_cpio_trailer( assert_cc(sizeof(trailer) % 4 == 0); *cpio_buffer = xreallocate_pool(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + sizeof(trailer)); - CopyMem((UINT8*) *cpio_buffer + *cpio_buffer_size, trailer, sizeof(trailer)); + memcpy((UINT8*) *cpio_buffer + *cpio_buffer_size, trailer, sizeof(trailer)); *cpio_buffer_size += sizeof(trailer); return EFI_SUCCESS; @@ -388,10 +388,10 @@ EFI_STATUS pack_cpio( continue; if (!is_ascii(dirent->FileName)) continue; - if (StrLen(dirent->FileName) > 255) /* Max filename size on Linux */ + if (strlen16(dirent->FileName) > 255) /* Max filename size on Linux */ continue; - d = xstrdup(dirent->FileName); + d = xstrdup16(dirent->FileName); if (n_items+2 > n_allocated) { UINTN m; @@ -418,7 +418,7 @@ EFI_STATUS pack_cpio( /* Now, sort the files we found, to make this uniform and stable (and to ensure the TPM measurements * are not dependent on read order) */ - sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) StrCmp); + sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) strcmp16); /* Generate the leading directory inodes right before adding the first files, to the * archive. Otherwise the cpio archive cannot be unpacked, since the leading dirs won't exist. */ diff --git a/src/boot/efi/devicetree.c b/src/boot/efi/devicetree.c index b8ba52a523..81c6e60ca6 100644 --- a/src/boot/efi/devicetree.c +++ b/src/boot/efi/devicetree.c @@ -51,7 +51,7 @@ static EFI_STATUS devicetree_fixup(struct devicetree_state *state, UINTN len) { if (EFI_ERROR(err)) return err; - CopyMem(PHYSICAL_ADDRESS_TO_POINTER(state->addr), oldptr, len); + memcpy(PHYSICAL_ADDRESS_TO_POINTER(state->addr), oldptr, len); err = BS->FreePages(oldaddr, oldpages); if (EFI_ERROR(err)) return err; @@ -122,7 +122,7 @@ EFI_STATUS devicetree_install_from_memory(struct devicetree_state *state, if (EFI_ERROR(err)) return err; - CopyMem(PHYSICAL_ADDRESS_TO_POINTER(state->addr), dtb_buffer, dtb_length); + memcpy(PHYSICAL_ADDRESS_TO_POINTER(state->addr), dtb_buffer, dtb_length); err = devicetree_fixup(state, dtb_length); if (EFI_ERROR(err)) diff --git a/src/boot/efi/efi-string.c b/src/boot/efi/efi-string.c new file mode 100644 index 0000000000..b93d0ed46a --- /dev/null +++ b/src/boot/efi/efi-string.c @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include + +#include "efi-string.h" + +#ifdef SD_BOOT +# include "util.h" +# define xmalloc(n) xallocate_pool(n) +#else +# include +# include "macro.h" +# define xmalloc(n) ASSERT_SE_PTR(malloc(n)) +#endif + +/* String functions for both char and char16_t that should behave the same way as their respective + * counterpart in userspace. Where it makes sense, these accept NULL and do something sensible whereas + * userspace does not allow for this (strlen8(NULL) returns 0 like strlen_ptr(NULL) for example). To make it + * easier to tell in code which kind of string they work on, we use 8/16 suffixes. This also makes is easier + * to unit test them. */ + +#define DEFINE_STRNLEN(type, name) \ + size_t name(const type *s, size_t n) { \ + if (!s) \ + return 0; \ + \ + size_t len = 0; \ + while (len < n && *s) { \ + s++; \ + len++; \ + } \ + \ + return len; \ + } + +DEFINE_STRNLEN(char, strnlen8); +DEFINE_STRNLEN(char16_t, strnlen16); + +size_t strlen8(const char *s) { + return strnlen8(s, SIZE_MAX); +} + +size_t strlen16(const char16_t *s) { + return strnlen16(s, SIZE_MAX); +} + +#define TOLOWER(c) \ + ({ \ + typeof(c) _c = (c); \ + (_c >= 'A' && _c <= 'Z') ? _c + ('a' - 'A') : _c; \ + }) + +#define DEFINE_STRTOLOWER(type, name) \ + void name(type *s) { \ + if (!s) \ + return; \ + for (; *s; s++) \ + *s = TOLOWER(*s); \ + } + +DEFINE_STRTOLOWER(char, strtolower8); +DEFINE_STRTOLOWER(char16_t, strtolower16); + +#define DEFINE_STRNCASECMP(type, name, tolower) \ + int name(const type *s1, const type *s2, size_t n) { \ + if (!s1 || !s2) \ + return CMP(s1, s2); \ + \ + while (n > 0) { \ + int c1 = *s1; \ + int c2 = *s2; \ + if (tolower) { \ + c1 = TOLOWER(c1); \ + c2 = TOLOWER(c2); \ + } \ + if (!c1 || c1 != c2) \ + return c1 - c2; \ + \ + s1++; \ + s2++; \ + n--; \ + } \ + \ + return 0; \ + } + +DEFINE_STRNCASECMP(char, strncmp8, false); +DEFINE_STRNCASECMP(char16_t, strncmp16, false); + +int strcmp8(const char *s1, const char *s2) { + return strncmp8(s1, s2, SIZE_MAX); +} + +int strcmp16(const char16_t *s1, const char16_t *s2) { + return strncmp16(s1, s2, SIZE_MAX); +} + +DEFINE_STRNCASECMP(char, strncasecmp8, true); +DEFINE_STRNCASECMP(char16_t, strncasecmp16, true); + +int strcasecmp8(const char *s1, const char *s2) { + return strncasecmp8(s1, s2, SIZE_MAX); +} + +int strcasecmp16(const char16_t *s1, const char16_t *s2) { + return strncasecmp16(s1, s2, SIZE_MAX); +} + +#define DEFINE_STRCPY(type, name) \ + type *name(type * restrict dest, const type * restrict src) { \ + assert(dest); \ + type *ret = dest; \ + \ + if (!src) { \ + *dest = '\0'; \ + return ret; \ + } \ + \ + while (*src) { \ + *dest = *src; \ + dest++; \ + src++; \ + } \ + \ + *dest = '\0'; \ + return ret; \ + } + +DEFINE_STRCPY(char, strcpy8); +DEFINE_STRCPY(char16_t, strcpy16); + +#define DEFINE_STRCHR(type, name) \ + type *name(const type *s, type c) { \ + if (!s) \ + return NULL; \ + \ + while (*s) { \ + if (*s == c) \ + return (type *) s; \ + s++; \ + } \ + \ + return NULL; \ + } + +DEFINE_STRCHR(char, strchr8); +DEFINE_STRCHR(char16_t, strchr16); + +#define DEFINE_STRNDUP(type, name, len_func) \ + type *name(const type *s, size_t n) { \ + if (!s) \ + return NULL; \ + \ + size_t len = len_func(s, n); \ + size_t size = len * sizeof(type); \ + \ + type *dup = xmalloc(size + sizeof(type)); \ + efi_memcpy(dup, s, size); \ + dup[len] = '\0'; \ + \ + return dup; \ + } + +DEFINE_STRNDUP(char, xstrndup8, strnlen8); +DEFINE_STRNDUP(char16_t, xstrndup16, strnlen16); + +char *xstrdup8(const char *s) { + return xstrndup8(s, SIZE_MAX); +} + +char16_t *xstrdup16(const char16_t *s) { + return xstrndup16(s, SIZE_MAX); +} + +int efi_memcmp(const void *p1, const void *p2, size_t n) { + if (!p1 || !p2) + return CMP(p1, p2); + + const uint8_t *up1 = p1, *up2 = p2; + while (n > 0) { + if (*up1 != *up2) + return *up1 - *up2; + + up1++; + up2++; + n--; + } + + return 0; +} + +void *efi_memcpy(void * restrict dest, const void * restrict src, size_t n) { + if (!dest || !src || n == 0) + return dest; + + uint8_t *d = dest; + const uint8_t *s = src; + + while (n > 0) { + *d = *s; + d++; + s++; + n--; + } + + return dest; +} + +void *efi_memset(void *p, int c, size_t n) { + if (!p || n == 0) + return p; + + uint8_t *q = p; + while (n > 0) { + *q = c; + q++; + n--; + } + + return p; +} + +#ifdef SD_BOOT +# undef memcmp +# undef memcpy +# undef memset +/* Provide the actual implementation for the builtins. To prevent a linker error, we mark memcpy/memset as + * weak, because gnu-efi is currently providing them. */ +__attribute__((alias("efi_memcmp"))) int memcmp(const void *p1, const void *p2, size_t n); +__attribute__((weak, alias("efi_memcpy"))) void *memcpy(void * restrict dest, const void * restrict src, size_t n); +__attribute__((weak, alias("efi_memset"))) void *memset(void *p, int c, size_t n); +#endif diff --git a/src/boot/efi/efi-string.h b/src/boot/efi/efi-string.h new file mode 100644 index 0000000000..c203c63c55 --- /dev/null +++ b/src/boot/efi/efi-string.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include +#include +#include + +#include "macro-fundamental.h" + +size_t strnlen8(const char *s, size_t n); +size_t strnlen16(const char16_t *s, size_t n); + +size_t strlen8(const char *s); +size_t strlen16(const char16_t *s); + +static inline size_t strsize8(const char *s) { + return s ? (strlen8(s) + 1) * sizeof(*s) : 0; +} + +static inline size_t strsize16(const char16_t *s) { + return s ? (strlen16(s) + 1) * sizeof(*s) : 0; +} + +void strtolower8(char *s); +void strtolower16(char16_t *s); + +int strncmp8(const char *s1, const char *s2, size_t n); +int strncmp16(const char16_t *s1, const char16_t *s2, size_t n); + +int strcmp8(const char *s1, const char *s2); +int strcmp16(const char16_t *s1, const char16_t *s2); + +int strncasecmp8(const char *s1, const char *s2, size_t n); +int strncasecmp16(const char16_t *s1, const char16_t *s2, size_t n); + +int strcasecmp8(const char *s1, const char *s2); +int strcasecmp16(const char16_t *s1, const char16_t *s2); + +static inline bool strneq8(const char *s1, const char *s2, size_t n) { + return strncmp8(s1, s2, n) == 0; +} + +static inline bool strneq16(const char16_t *s1, const char16_t *s2, size_t n) { + return strncmp16(s1, s2, n) == 0; +} + +static inline bool streq8(const char *s1, const char *s2) { + return strcmp8(s1, s2) == 0; +} + +static inline bool streq16(const char16_t *s1, const char16_t *s2) { + return strcmp16(s1, s2) == 0; +} + +static inline int strncaseeq8(const char *s1, const char *s2, size_t n) { + return strncasecmp8(s1, s2, n) == 0; +} + +static inline int strncaseeq16(const char16_t *s1, const char16_t *s2, size_t n) { + return strncasecmp16(s1, s2, n) == 0; +} + +static inline bool strcaseeq8(const char *s1, const char *s2) { + return strcasecmp8(s1, s2) == 0; +} + +static inline bool strcaseeq16(const char16_t *s1, const char16_t *s2) { + return strcasecmp16(s1, s2) == 0; +} + +char *strcpy8(char * restrict dest, const char * restrict src); +char16_t *strcpy16(char16_t * restrict dest, const char16_t * restrict src); + +char *strchr8(const char *s, char c); +char16_t *strchr16(const char16_t *s, char16_t c); + +char *xstrndup8(const char *s, size_t n); +char16_t *xstrndup16(const char16_t *s, size_t n); + +char *xstrdup8(const char *s); +char16_t *xstrdup16(const char16_t *s); + +#ifdef SD_BOOT +/* The compiler normaly has knowledge about standard functions such as memcmp, but this is not the case when + * compiling with -ffreestanding. By referring to builtins, the compiler can check arguments and do + * optimizations again. Note that we still need to provide implementations as the compiler is free to not + * inline its own implementation and instead issue a library call. */ +# define memcmp __builtin_memcmp +# define memcpy __builtin_memcpy +# define memset __builtin_memset +#endif + +/* The actual implementations of builtins with efi_ prefix so we can unit test them. */ +int efi_memcmp(const void *p1, const void *p2, size_t n); +void *efi_memcpy(void * restrict dest, const void * restrict src, size_t n); +void *efi_memset(void *p, int c, size_t n); diff --git a/src/boot/efi/initrd.c b/src/boot/efi/initrd.c index 3136d3b8fa..2d0984990b 100644 --- a/src/boot/efi/initrd.c +++ b/src/boot/efi/initrd.c @@ -61,7 +61,7 @@ EFIAPI EFI_STATUS initrd_load_file( return EFI_BUFFER_TOO_SMALL; } - CopyMem(buffer, loader->address, loader->length); + memcpy(buffer, loader->address, loader->length); *buffer_size = loader->length; return EFI_SUCCESS; } diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c index f04f81fb05..dcffea15c0 100644 --- a/src/boot/efi/linux.c +++ b/src/boot/efi/linux.c @@ -45,7 +45,7 @@ static EFI_STATUS loaded_image_register( /* if a cmdline is set convert it to UCS2 */ if (cmdline) { loaded_image->LoadOptions = xstra_to_str(cmdline); - loaded_image->LoadOptionsSize = StrSize(loaded_image->LoadOptions); + loaded_image->LoadOptionsSize = strsize16(loaded_image->LoadOptions); } /* install a new LoadedImage protocol. ret_handle is a new image handle */ @@ -145,9 +145,9 @@ EFI_STATUS linux_exec( if (EFI_ERROR(err)) return EFI_OUT_OF_RESOURCES; new_buffer = PHYSICAL_ADDRESS_TO_POINTER(ALIGN_TO(kernel.addr, kernel_alignment)); - CopyMem(new_buffer, linux_buffer, linux_length); + memcpy(new_buffer, linux_buffer, linux_length); /* zero out rest of memory (probably not needed, but BSS section should be 0) */ - SetMem((UINT8 *)new_buffer + linux_length, kernel_size_of_image - linux_length, 0); + memset((UINT8 *)new_buffer + linux_length, 0, kernel_size_of_image - linux_length); /* get the entry point inside the relocated kernel */ kernel_entry = (EFI_IMAGE_ENTRY_POINT) ((const UINT8 *)new_buffer + kernel_entry_address); diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c index 15052bdff6..a6c1f06939 100644 --- a/src/boot/efi/linux_x86.c +++ b/src/boot/efi/linux_x86.c @@ -159,7 +159,7 @@ EFI_STATUS linux_exec( return err; boot_params = (struct boot_params *) PHYSICAL_ADDRESS_TO_POINTER(addr); - ZeroMem(boot_params, 0x4000); + memset(boot_params, 0, 0x4000); boot_params->hdr = image_params->hdr; boot_params->hdr.type_of_loader = 0xff; setup_sectors = image_params->hdr.setup_sects > 0 ? image_params->hdr.setup_sects : 4; @@ -176,7 +176,7 @@ EFI_STATUS linux_exec( if (EFI_ERROR(err)) return err; - CopyMem(PHYSICAL_ADDRESS_TO_POINTER(addr), cmdline, cmdline_len); + memcpy(PHYSICAL_ADDRESS_TO_POINTER(addr), cmdline, cmdline_len); ((CHAR8 *) PHYSICAL_ADDRESS_TO_POINTER(addr))[cmdline_len] = 0; boot_params->hdr.cmd_line_ptr = (UINT32) addr; } diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index da4fd18ea8..c9ce8f19e0 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -25,14 +25,14 @@ static EFI_STATUS tpm1_measure_to_pcr_and_event_log( assert(tcg); assert(description); - desc_len = StrSize(description); + desc_len = strsize16(description); tcg_event = xallocate_zero_pool(offsetof(TCG_PCR_EVENT, Event) + desc_len); *tcg_event = (TCG_PCR_EVENT) { .EventSize = desc_len, .PCRIndex = pcrindex, .EventType = EV_IPL, }; - CopyMem(tcg_event->Event, description, desc_len); + memcpy(tcg_event->Event, description, desc_len); return tcg->HashLogExtendEvent( (EFI_TCG *) tcg, @@ -56,7 +56,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log( assert(tcg); assert(description); - desc_len = StrSize(description); + desc_len = strsize16(description); tcg_event = xallocate_zero_pool(offsetof(EFI_TCG2_EVENT, Event) + desc_len); *tcg_event = (EFI_TCG2_EVENT) { .Size = offsetof(EFI_TCG2_EVENT, Event) + desc_len, @@ -66,7 +66,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log( .Header.EventType = EV_IPL, }; - CopyMem(tcg_event->Event, description, desc_len); + memcpy(tcg_event->Event, description, desc_len); return tcg->HashLogExtendEvent( tcg, @@ -171,7 +171,7 @@ EFI_STATUS tpm_log_load_options(const CHAR16 *load_options) { err = tpm_log_event(pcr, POINTER_TO_PHYSICAL_ADDRESS(load_options), - StrSize(load_options), load_options); + strsize16(load_options), load_options); if (EFI_ERROR(err)) return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err); } diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 8f1645202b..1e42f8b08e 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -194,6 +194,7 @@ efi_cflags = cc.get_supported_arguments( '-isystem', efi_incdir, '-isystem', efi_incdir / efi_arch[1], '-I', fundamental_path, + '-I', meson.current_source_dir(), '-DSD_BOOT', '-DGNU_EFI_USE_MS_ABI', '-include', efi_config_h, @@ -331,6 +332,7 @@ efi_headers = files( 'devicetree.h', 'disk.h', 'drivers.h', + 'efi-string.h', 'graphics.h', 'initrd.h', 'linux.h', @@ -350,6 +352,7 @@ common_sources = files( 'assert.c', 'devicetree.c', 'disk.c', + 'efi-string.c', 'graphics.c', 'initrd.c', 'measure.c', @@ -380,18 +383,22 @@ else stub_sources += files('linux.c') endif +tests += [ + [files('test-efi-string.c', 'efi-string.c')], +] + # BCD parser only makes sense on arches that Windows supports. if efi_arch[1] in ['ia32', 'x86_64', 'arm', 'aarch64'] systemd_boot_sources += files('bcd.c') tests += [ - [files('test-bcd.c'), + [files('test-bcd.c', 'efi-string.c'), [], [libzstd], [], 'HAVE_ZSTD'], ] fuzzers += [ - [files('fuzz-bcd.c')], + [files('fuzz-bcd.c', 'efi-string.c')], ] endif diff --git a/src/boot/efi/pe.c b/src/boot/efi/pe.c index 568dcf4012..f9bd57f0ce 100644 --- a/src/boot/efi/pe.c +++ b/src/boot/efi/pe.c @@ -119,12 +119,12 @@ struct PeSectionHeader { static inline BOOLEAN verify_dos(const struct DosFileHeader *dos) { assert(dos); - return CompareMem(dos->Magic, DOS_FILE_MAGIC, STRLEN(DOS_FILE_MAGIC)) == 0; + return memcmp(dos->Magic, DOS_FILE_MAGIC, STRLEN(DOS_FILE_MAGIC)) == 0; } static inline BOOLEAN verify_pe(const struct PeFileHeader *pe, BOOLEAN allow_compatibility) { assert(pe); - return CompareMem(pe->Magic, PE_FILE_MAGIC, STRLEN(PE_FILE_MAGIC)) == 0 && + return memcmp(pe->Magic, PE_FILE_MAGIC, STRLEN(PE_FILE_MAGIC)) == 0 && (pe->FileHeader.Machine == TARGET_MACHINE_TYPE || (allow_compatibility && pe->FileHeader.Machine == TARGET_MACHINE_TYPE_COMPATIBILITY)) && pe->FileHeader.NumberOfSections > 0 && @@ -154,7 +154,7 @@ static void locate_sections( const struct PeSectionHeader *sect = section_table + i; for (UINTN j = 0; sections[j]; j++) { - if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0) + if (memcmp(sect->Name, sections[j], strlen8((const char *) sections[j])) != 0) continue; if (addrs) diff --git a/src/boot/efi/random-seed.c b/src/boot/efi/random-seed.c index b01e232f63..a9ee273673 100644 --- a/src/boot/efi/random-seed.c +++ b/src/boot/efi/random-seed.c @@ -220,10 +220,10 @@ static void validate_sha256(void) { uint8_t result[HASH_VALUE_SIZE]; sha256_init_ctx(&hash); - sha256_process_bytes(array[i].string, strlena((const CHAR8*) array[i].string), &hash); + sha256_process_bytes(array[i].string, strlen8(array[i].string), &hash); sha256_finish_ctx(&hash, result); - assert(CompareMem(result, array[i].hash, HASH_VALUE_SIZE) == 0); + assert(memcmp(result, array[i].hash, HASH_VALUE_SIZE) == 0); } #endif diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c index 71bd008d96..e0d075c911 100644 --- a/src/boot/efi/splash.c +++ b/src/boot/efi/splash.c @@ -271,7 +271,7 @@ EFI_STATUS graphics_splash(const UINT8 *content, UINTN len, const EFI_GRAPHICS_O assert(content); if (!background) { - if (StriCmp(L"Apple", ST->FirmwareVendor) == 0) { + if (strcaseeq16(u"Apple", ST->FirmwareVendor)) { pixel.Red = 0xc0; pixel.Green = 0xc0; pixel.Blue = 0xc0; diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 40f615b2b3..36becafa08 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -68,28 +68,28 @@ static EFI_STATUS combine_initrd( /* Order matters, the real initrd must come first, since it might include microcode updates * which the kernel only looks for in the first cpio archive */ - CopyMem(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size); + memcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size); p += initrd_size; pad = ALIGN_TO(initrd_size, 4) - initrd_size; if (pad > 0) { - ZeroMem(p, pad); + memset(p, 0, pad); p += pad; } } if (credential_initrd) { - CopyMem(p, credential_initrd, credential_initrd_size); + memcpy(p, credential_initrd, credential_initrd_size); p += credential_initrd_size; } if (global_credential_initrd) { - CopyMem(p, global_credential_initrd, global_credential_initrd_size); + memcpy(p, global_credential_initrd, global_credential_initrd_size); p += global_credential_initrd_size; } if (sysext_initrd) { - CopyMem(p, sysext_initrd, sysext_initrd_size); + memcpy(p, sysext_initrd, sysext_initrd_size); p += sysext_initrd_size; } diff --git a/src/boot/efi/test-efi-string.c b/src/boot/efi/test-efi-string.c new file mode 100644 index 0000000000..d5044d801c --- /dev/null +++ b/src/boot/efi/test-efi-string.c @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "efi-string.h" +#include "tests.h" + +TEST(strlen8) { + assert_se(strlen8(NULL) == 0); + assert_se(strlen8("") == 0); + assert_se(strlen8("1") == 1); + assert_se(strlen8("11") == 2); + assert_se(strlen8("123456789") == 9); + assert_se(strlen8("12\0004") == 2); +} + +TEST(strlen16) { + assert_se(strlen16(NULL) == 0); + assert_se(strlen16(u"") == 0); + assert_se(strlen16(u"1") == 1); + assert_se(strlen16(u"11") == 2); + assert_se(strlen16(u"123456789") == 9); + assert_se(strlen16(u"12\0004") == 2); +} + +TEST(strnlen8) { + assert_se(strnlen8(NULL, 0) == 0); + assert_se(strnlen8(NULL, 10) == 0); + assert_se(strnlen8("", 10) == 0); + assert_se(strnlen8("1", 10) == 1); + assert_se(strnlen8("11", 1) == 1); + assert_se(strnlen8("123456789", 7) == 7); + assert_se(strnlen8("12\0004", 5) == 2); +} + +TEST(strnlen16) { + assert_se(strnlen16(NULL, 0) == 0); + assert_se(strnlen16(NULL, 10) == 0); + assert_se(strnlen16(u"", 10) == 0); + assert_se(strnlen16(u"1", 10) == 1); + assert_se(strnlen16(u"11", 1) == 1); + assert_se(strnlen16(u"123456789", 7) == 7); + assert_se(strnlen16(u"12\0004", 5) == 2); +} + +TEST(strsize8) { + assert_se(strsize8(NULL) == 0); + assert_se(strsize8("") == 1); + assert_se(strsize8("1") == 2); + assert_se(strsize8("11") == 3); + assert_se(strsize8("123456789") == 10); + assert_se(strsize8("12\0004") == 3); +} + +TEST(strsize16) { + assert_se(strsize16(NULL) == 0); + assert_se(strsize16(u"") == 2); + assert_se(strsize16(u"1") == 4); + assert_se(strsize16(u"11") == 6); + assert_se(strsize16(u"123456789") == 20); + assert_se(strsize16(u"12\0004") == 6); +} + +TEST(strtolower8) { + char s[] = "\0001234abcDEF!\0zZ"; + + strtolower8(NULL); + + strtolower8(s); + assert_se(memcmp(s, "\0001234abcDEF!\0zZ", sizeof(s)) == 0); + + s[0] = '#'; + strtolower8(s); + assert_se(memcmp(s, "#1234abcdef!\0zZ", sizeof(s)) == 0); +} + +TEST(strtolower16) { + char16_t s[] = u"\0001234abcDEF!\0zZ"; + + strtolower16(NULL); + + strtolower16(s); + assert_se(memcmp(s, u"\0001234abcDEF!\0zZ", sizeof(s)) == 0); + + s[0] = '#'; + strtolower16(s); + assert_se(memcmp(s, u"#1234abcdef!\0zZ", sizeof(s)) == 0); +} + +TEST(strncmp8) { + assert_se(strncmp8(NULL, "", 10) < 0); + assert_se(strncmp8("", NULL, 10) > 0); + assert_se(strncmp8(NULL, NULL, 0) == 0); + assert_se(strncmp8(NULL, NULL, 10) == 0); + assert_se(strncmp8("", "", 10) == 0); + assert_se(strncmp8("abc", "abc", 2) == 0); + assert_se(strncmp8("aBc", "aBc", 3) == 0); + assert_se(strncmp8("aBC", "aBC", 4) == 0); + assert_se(strncmp8("", "a", 0) == 0); + assert_se(strncmp8("b", "a", 0) == 0); + assert_se(strncmp8("", "a", 3) < 0); + assert_se(strncmp8("=", "=", 1) == 0); + assert_se(strncmp8("A", "a", 1) < 0); + assert_se(strncmp8("a", "A", 2) > 0); + assert_se(strncmp8("a", "Aa", 2) > 0); + assert_se(strncmp8("12\00034", "12345", 4) < 0); + assert_se(strncmp8("12\00034", "12345", SIZE_MAX) < 0); + assert_se(strncmp8("abc\0def", "abc", SIZE_MAX) == 0); + assert_se(strncmp8("abc\0def", "abcdef", SIZE_MAX) < 0); + + assert_se(strncmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MIN }, 1) == 0); + assert_se(strncmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MAX }, 1) == 0); + assert_se(strncmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MAX }, 1) < 0); + assert_se(strncmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MIN }, 1) > 0); +} + +TEST(strncmp16) { + assert_se(strncmp16(NULL, u"", 10) < 0); + assert_se(strncmp16(u"", NULL, 10) > 0); + assert_se(strncmp16(NULL, NULL, 0) == 0); + assert_se(strncmp16(NULL, NULL, 10) == 0); + assert_se(strncmp16(u"", u"", 0) == 0); + assert_se(strncmp16(u"", u"", 10) == 0); + assert_se(strncmp16(u"abc", u"abc", 2) == 0); + assert_se(strncmp16(u"aBc", u"aBc", 3) == 0); + assert_se(strncmp16(u"aBC", u"aBC", 4) == 0); + assert_se(strncmp16(u"", u"a", 0) == 0); + assert_se(strncmp16(u"b", u"a", 0) == 0); + assert_se(strncmp16(u"", u"a", 3) < 0); + assert_se(strncmp16(u"=", u"=", 1) == 0); + assert_se(strncmp16(u"A", u"a", 1) < 0); + assert_se(strncmp16(u"a", u"A", 2) > 0); + assert_se(strncmp16(u"a", u"Aa", 2) > 0); + assert_se(strncmp16(u"12\00034", u"12345", 4) < 0); + assert_se(strncmp16(u"12\00034", u"12345", SIZE_MAX) < 0); + assert_se(strncmp16(u"abc\0def", u"abc", SIZE_MAX) == 0); + assert_se(strncmp16(u"abc\0def", u"abcdef", SIZE_MAX) < 0); + + assert_se(strncmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ UINT16_MAX }, 1) == 0); + assert_se(strncmp16((char16_t[]){ 0 }, (char16_t[]){ UINT16_MAX }, 1) < 0); + assert_se(strncmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ 0 }, 1) > 0); +} + +TEST(strncasecmp8) { + assert_se(strncasecmp8(NULL, "", 10) < 0); + assert_se(strncasecmp8("", NULL, 10) > 0); + assert_se(strncasecmp8(NULL, NULL, 0) == 0); + assert_se(strncasecmp8(NULL, NULL, 10) == 0); + assert_se(strncasecmp8("", "", 10) == 0); + assert_se(strncasecmp8("abc", "abc", 2) == 0); + assert_se(strncasecmp8("aBc", "AbC", 3) == 0); + assert_se(strncasecmp8("aBC", "Abc", 4) == 0); + assert_se(strncasecmp8("", "a", 0) == 0); + assert_se(strncasecmp8("b", "a", 0) == 0); + assert_se(strncasecmp8("", "a", 3) < 0); + assert_se(strncasecmp8("=", "=", 1) == 0); + assert_se(strncasecmp8("A", "a", 1) == 0); + assert_se(strncasecmp8("a", "A", 2) == 0); + assert_se(strncasecmp8("a", "Aa", 2) < 0); + assert_se(strncasecmp8("12\00034", "12345", 4) < 0); + assert_se(strncasecmp8("12\00034", "12345", SIZE_MAX) < 0); + assert_se(strncasecmp8("abc\0def", "ABC", SIZE_MAX) == 0); + assert_se(strncasecmp8("abc\0def", "ABCDEF", SIZE_MAX) < 0); + + assert_se(strncasecmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MIN }, 1) == 0); + assert_se(strncasecmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MAX }, 1) == 0); + assert_se(strncasecmp8((char[]){ CHAR_MIN }, (char[]){ CHAR_MAX }, 1) < 0); + assert_se(strncasecmp8((char[]){ CHAR_MAX }, (char[]){ CHAR_MIN }, 1) > 0); +} + +TEST(strncasecmp16) { + assert_se(strncasecmp16(NULL, u"", 10) < 0); + assert_se(strncasecmp16(u"", NULL, 10) > 0); + assert_se(strncasecmp16(NULL, NULL, 0) == 0); + assert_se(strncasecmp16(NULL, NULL, 10) == 0); + assert_se(strncasecmp16(u"", u"", 10) == 0); + assert_se(strncasecmp16(u"abc", u"abc", 2) == 0); + assert_se(strncasecmp16(u"aBc", u"AbC", 3) == 0); + assert_se(strncasecmp16(u"aBC", u"Abc", 4) == 0); + assert_se(strncasecmp16(u"", u"a", 0) == 0); + assert_se(strncasecmp16(u"b", u"a", 0) == 0); + assert_se(strncasecmp16(u"", u"a", 3) < 0); + assert_se(strncasecmp16(u"=", u"=", 1) == 0); + assert_se(strncasecmp16(u"A", u"a", 1) == 0); + assert_se(strncasecmp16(u"a", u"A", 2) == 0); + assert_se(strncasecmp16(u"a", u"Aa", 2) < 0); + assert_se(strncasecmp16(u"12\00034", u"12345", 4) < 0); + assert_se(strncasecmp16(u"12\00034", u"12345", SIZE_MAX) < 0); + assert_se(strncasecmp16(u"abc\0def", u"ABC", SIZE_MAX) == 0); + assert_se(strncasecmp16(u"abc\0def", u"ABCDEF", SIZE_MAX) < 0); + + assert_se(strncasecmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ UINT16_MAX }, 1) == 0); + assert_se(strncasecmp16((char16_t[]){ 0 }, (char16_t[]){ UINT16_MAX }, 1) < 0); + assert_se(strncasecmp16((char16_t[]){ UINT16_MAX }, (char16_t[]){ 0 }, 1) > 0); +} + +TEST(strcpy8) { + char buf[128]; + + assert_se(strcpy8(buf, "123") == buf); + assert_se(streq8(buf, "123")); + assert_se(strcpy8(buf, "") == buf); + assert_se(streq8(buf, "")); + assert_se(strcpy8(buf, "A") == buf); + assert_se(streq8(buf, "A")); + assert_se(strcpy8(buf, NULL) == buf); + assert_se(streq8(buf, "")); +} + +TEST(strcpy16) { + char16_t buf[128]; + + assert_se(strcpy16(buf, u"123") == buf); + assert_se(streq16(buf, u"123")); + assert_se(strcpy16(buf, u"") == buf); + assert_se(streq16(buf, u"")); + assert_se(strcpy16(buf, u"A") == buf); + assert_se(streq16(buf, u"A")); + assert_se(strcpy16(buf, NULL) == buf); + assert_se(streq16(buf, u"")); +} + +TEST(strchr8) { + assert_se(!strchr8(NULL, 'a')); + assert_se(!strchr8("", 'a')); + assert_se(!strchr8("123", 'a')); + + const char str[] = "abcaBc"; + assert_se(strchr8(str, 'a') == &str[0]); + assert_se(strchr8(str, 'c') == &str[2]); + assert_se(strchr8(str, 'B') == &str[4]); +} + +TEST(strchr16) { + assert_se(!strchr16(NULL, 'a')); + assert_se(!strchr16(u"", 'a')); + assert_se(!strchr16(u"123", 'a')); + + const char16_t str[] = u"abcaBc"; + assert_se(strchr16(str, 'a') == &str[0]); + assert_se(strchr16(str, 'c') == &str[2]); + assert_se(strchr16(str, 'B') == &str[4]); +} + +TEST(xstrndup8) { + char *s = NULL; + + assert_se(xstrndup8(NULL, 0) == NULL); + assert_se(xstrndup8(NULL, 10) == NULL); + + assert_se(s = xstrndup8("", 10)); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrndup8("abc", 0)); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrndup8("ABC", 3)); + assert_se(streq8(s, "ABC")); + free(s); + + assert_se(s = xstrndup8("123abcDEF", 5)); + assert_se(streq8(s, "123ab")); + free(s); +} + +TEST(xstrdup8) { + char *s = NULL; + + assert_se(xstrdup8(NULL) == NULL); + + assert_se(s = xstrdup8("")); + assert_se(streq8(s, "")); + free(s); + + assert_se(s = xstrdup8("1")); + assert_se(streq8(s, "1")); + free(s); + + assert_se(s = xstrdup8("123abcDEF")); + assert_se(streq8(s, "123abcDEF")); + free(s); +} + +TEST(xstrndup16) { + char16_t *s = NULL; + + assert_se(xstrndup16(NULL, 0) == NULL); + assert_se(xstrndup16(NULL, 10) == NULL); + + assert_se(s = xstrndup16(u"", 10)); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrndup16(u"abc", 0)); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrndup16(u"ABC", 3)); + assert_se(streq16(s, u"ABC")); + free(s); + + assert_se(s = xstrndup16(u"123abcDEF", 5)); + assert_se(streq16(s, u"123ab")); + free(s); +} + +TEST(xstrdup16) { + char16_t *s = NULL; + + assert_se(xstrdup16(NULL) == NULL); + + assert_se(s = xstrdup16(u"")); + assert_se(streq16(s, u"")); + free(s); + + assert_se(s = xstrdup16(u"1")); + assert_se(streq16(s, u"1")); + free(s); + + assert_se(s = xstrdup16(u"123abcDEF")); + assert_se(streq16(s, u"123abcDEF")); + free(s); +} + +TEST(efi_memcmp) { + assert_se(efi_memcmp(NULL, NULL, 0) == 0); + assert_se(efi_memcmp(NULL, NULL, 1) == 0); + assert_se(efi_memcmp(NULL, "", 1) < 0); + assert_se(efi_memcmp("", NULL, 1) > 0); + assert_se(efi_memcmp("", "", 0) == 0); + assert_se(efi_memcmp("", "", 1) == 0); + assert_se(efi_memcmp("1", "1", 1) == 0); + assert_se(efi_memcmp("1", "2", 1) < 0); + assert_se(efi_memcmp("A", "a", 1) < 0); + assert_se(efi_memcmp("a", "A", 1) > 0); + assert_se(efi_memcmp("abc", "ab", 2) == 0); + assert_se(efi_memcmp("ab", "abc", 3) < 0); + assert_se(efi_memcmp("ab\000bd", "ab\000bd", 6) == 0); + assert_se(efi_memcmp("ab\000b\0", "ab\000bd", 6) < 0); +} + +TEST(efi_memcpy) { + char buf[10]; + + assert_se(!efi_memcpy(NULL, NULL, 0)); + assert_se(!efi_memcpy(NULL, "", 1)); + assert_se(efi_memcpy(buf, NULL, 0) == buf); + assert_se(efi_memcpy(buf, NULL, 1) == buf); + assert_se(efi_memcpy(buf, "a", 0) == buf); + + assert_se(efi_memcpy(buf, "", 1) == buf); + assert_se(memcmp(buf, "", 1) == 0); + assert_se(efi_memcpy(buf, "1", 1) == buf); + assert_se(memcmp(buf, "1", 1) == 0); + assert_se(efi_memcpy(buf, "23", 3) == buf); + assert_se(memcmp(buf, "23", 3) == 0); + assert_se(efi_memcpy(buf, "45\0ab\0\0\0c", 9) == buf); + assert_se(memcmp(buf, "45\0ab\0\0\0c", 9) == 0); +} + +TEST(efi_memset) { + char buf[10]; + + assert_se(!efi_memset(NULL, '1', 0)); + assert_se(!efi_memset(NULL, '1', 1)); + assert_se(efi_memset(buf, '1', 0) == buf); + + assert_se(efi_memset(buf, '2', 1) == buf); + assert_se(memcmp(buf, "2", 1) == 0); + assert_se(efi_memset(buf, '4', 4) == buf); + assert_se(memcmp(buf, "4444", 4) == 0); + assert_se(efi_memset(buf, 'a', 10) == buf); + assert_se(memcmp(buf, "aaaaaaaaaa", 10) == 0); +} + +DEFINE_TEST_MAIN(LOG_INFO); diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c index 169add8680..06859d2f3a 100644 --- a/src/boot/efi/util.c +++ b/src/boot/efi/util.c @@ -12,22 +12,14 @@ EFI_STATUS parse_boolean(const CHAR8 *v, BOOLEAN *b) { if (!v) return EFI_INVALID_PARAMETER; - if (strcmpa(v, (CHAR8 *)"1") == 0 || - strcmpa(v, (CHAR8 *)"yes") == 0 || - strcmpa(v, (CHAR8 *)"y") == 0 || - strcmpa(v, (CHAR8 *)"true") == 0 || - strcmpa(v, (CHAR8 *)"t") == 0 || - strcmpa(v, (CHAR8 *)"on") == 0) { + if (streq8((char *) v, "1") || streq8((char *) v, "yes") || streq8((char *) v, "y") || + streq8((char *) v, "true") || streq8((char *) v, "t") || streq8((char *) v, "on")) { *b = TRUE; return EFI_SUCCESS; } - if (strcmpa(v, (CHAR8 *)"0") == 0 || - strcmpa(v, (CHAR8 *)"no") == 0 || - strcmpa(v, (CHAR8 *)"n") == 0 || - strcmpa(v, (CHAR8 *)"false") == 0 || - strcmpa(v, (CHAR8 *)"f") == 0 || - strcmpa(v, (CHAR8 *)"off") == 0) { + if (streq8((char *) v, "0") || streq8((char *) v, "no") || streq8((char *) v, "n") || + streq8((char *) v, "false") || streq8((char *) v, "f") || streq8((char *) v, "off")) { *b = FALSE; return EFI_SUCCESS; } @@ -48,7 +40,7 @@ EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 * assert(vendor); assert(name); - return efivar_set_raw(vendor, name, value, value ? StrSize(value) : 0, flags); + return efivar_set_raw(vendor, name, value, value ? strsize16(value) : 0, flags); } EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN i, UINT32 flags) { @@ -125,7 +117,7 @@ EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value /* Make sure a terminating NUL is available at the end */ val = xallocate_pool(size + sizeof(CHAR16)); - CopyMem(val, buf, size); + memcpy(val, buf, size); val[size / sizeof(CHAR16) - 1] = 0; /* NUL terminate */ *value = val; @@ -306,7 +298,7 @@ CHAR16 *xstra_to_str(const CHAR8 *stra) { assert(stra); - len = strlena(stra); + len = strlen8((const char *) stra); str = xnew(CHAR16, len + 1); strlen = 0; @@ -336,7 +328,7 @@ CHAR16 *xstra_to_path(const CHAR8 *stra) { assert(stra); - len = strlena(stra); + len = strlen8((const char *) stra); str = xnew(CHAR16, len + 2); str[0] = '\\'; @@ -367,18 +359,6 @@ CHAR16 *xstra_to_path(const CHAR8 *stra) { return str; } -CHAR8 *strchra(const CHAR8 *s, CHAR8 c) { - if (!s) - return NULL; - - do { - if (*s == c) - return (CHAR8*) s; - } while (*s++); - - return NULL; -} - EFI_STATUS file_read(EFI_FILE *dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **ret, UINTN *ret_size) { _cleanup_(file_closep) EFI_FILE *handle = NULL; _cleanup_freepool_ CHAR8 *buf = NULL; @@ -417,7 +397,7 @@ EFI_STATUS file_read(EFI_FILE *dir, const CHAR16 *name, UINTN off, UINTN size, C return err; /* Note that handle->Read() changes size to reflect the actually bytes read. */ - ZeroMem(buf + size, extra); + memset(buf + size, 0, extra); *ret = TAKE_PTR(buf); if (ret_size) @@ -572,60 +552,6 @@ EFI_STATUS readdir_harder( return EFI_SUCCESS; } -UINTN strnlena(const CHAR8 *p, UINTN maxlen) { - UINTN c; - - if (!p) - return 0; - - for (c = 0; c < maxlen; c++) - if (p[c] == 0) - break; - - return c; -} - -INTN strncasecmpa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen) { - if (!a || !b) - return CMP(a, b); - - while (maxlen > 0) { - CHAR8 ca = *a, cb = *b; - if (ca >= 'A' && ca <= 'Z') - ca += 'a' - 'A'; - if (cb >= 'A' && cb <= 'Z') - cb += 'a' - 'A'; - if (!ca || ca != cb) - return ca - cb; - - a++; - b++; - maxlen--; - } - - return 0; -} - -CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz) { - CHAR8 *n; - - /* Following efilib's naming scheme this function would be called strndupa(), but we already have a - * function named like this in userspace, and it does something different there, hence to minimize - * confusion, let's pick a different name here */ - - assert(p || sz == 0); - - sz = strnlena(p, sz); - - n = xallocate_pool(sz + 1); - - if (sz > 0) - CopyMem(n, p, sz); - n[sz] = 0; - - return n; -} - BOOLEAN is_ascii(const CHAR16 *f) { if (!f) return FALSE; diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h index af204e9ab5..06c298d776 100644 --- a/src/boot/efi/util.h +++ b/src/boot/efi/util.h @@ -3,11 +3,10 @@ #include #include +#include #include "string-util-fundamental.h" -#define offsetof(type, member) __builtin_offsetof(type, member) - #define UINTN_MAX (~(UINTN)0) #define INTN_MAX ((INTN)(UINTN_MAX>>1)) #ifndef UINT32_MAX @@ -42,7 +41,6 @@ assert_cc(sizeof(int) == sizeof(UINT32)); #define xallocate_zero_pool(size) ASSERT_SE_PTR(AllocateZeroPool(size)) #define xreallocate_pool(p, old_size, new_size) ASSERT_SE_PTR(ReallocatePool((p), (old_size), (new_size))) #define xpool_print(fmt, ...) ((CHAR16 *) ASSERT_SE_PTR(PoolPrint((fmt), ##__VA_ARGS__))) -#define xstrdup(str) ((CHAR16 *) ASSERT_SE_PTR(StrDuplicate(str))) #define xnew(type, n) xnew_alloc(type, (n), xallocate_pool) #define xnew0(type, n) xnew_alloc(type, (n), xallocate_zero_pool) @@ -62,7 +60,6 @@ EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret); EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret); -CHAR8 *strchra(const CHAR8 *s, CHAR8 c); CHAR16 *xstra_to_path(const CHAR8 *stra); CHAR16 *xstra_to_str(const CHAR8 *stra); @@ -114,20 +111,13 @@ EFI_STATUS log_oom(void); void print_at(UINTN x, UINTN y, UINTN attr, const CHAR16 *str); void clear_screen(UINTN attr); -typedef INTN (*compare_pointer_func_t)(const void *a, const void *b); +typedef int (*compare_pointer_func_t)(const void *a, const void *b); void sort_pointer_array(void **array, UINTN n_members, compare_pointer_func_t compare); EFI_STATUS get_file_info_harder(EFI_FILE *handle, EFI_FILE_INFO **ret, UINTN *ret_size); EFI_STATUS readdir_harder(EFI_FILE *handle, EFI_FILE_INFO **buffer, UINTN *buffer_size); -UINTN strnlena(const CHAR8 *p, UINTN maxlen); -CHAR8 *xstrndup8(const CHAR8 *p, UINTN sz); -INTN strncasecmpa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen); -static inline BOOLEAN strncaseeqa(const CHAR8 *a, const CHAR8 *b, UINTN maxlen) { - return strncasecmpa(a, b, maxlen) == 0; -} - BOOLEAN is_ascii(const CHAR16 *f); CHAR16 **strv_free(CHAR16 **l); diff --git a/src/boot/efi/xbootldr.c b/src/boot/efi/xbootldr.c index f73b5eeb20..bc82768715 100644 --- a/src/boot/efi/xbootldr.c +++ b/src/boot/efi/xbootldr.c @@ -19,7 +19,7 @@ static EFI_DEVICE_PATH *path_chop(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) UINTN len = (UINT8 *) node - (UINT8 *) path; EFI_DEVICE_PATH *chopped = xallocate_pool(len + END_DEVICE_PATH_LENGTH); - CopyMem(chopped, path, len); + memcpy(chopped, path, len); SetDevicePathEndNode((EFI_DEVICE_PATH *) ((UINT8 *) chopped + len)); return chopped; @@ -35,7 +35,7 @@ static BOOLEAN verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_ h = &gpt_header_buffer->gpt_header; /* Some superficial validation of the GPT header */ - if (CompareMem(&h->Header.Signature, "EFI PART", sizeof(h->Header.Signature)) != 0) + if (memcmp(&h->Header.Signature, "EFI PART", sizeof(h->Header.Signature)) != 0) return FALSE; if (h->Header.HeaderSize < 92 || h->Header.HeaderSize > 512) @@ -123,12 +123,12 @@ static EFI_STATUS try_gpt( entry = (EFI_PARTITION_ENTRY*) ((UINT8*) entries + gpt.gpt_header.SizeOfPartitionEntry * i); - if (CompareMem(&entry->PartitionTypeGUID, XBOOTLDR_GUID, sizeof(entry->PartitionTypeGUID)) != 0) + if (memcmp(&entry->PartitionTypeGUID, XBOOTLDR_GUID, sizeof(entry->PartitionTypeGUID)) != 0) continue; /* Let's use memcpy(), in case the structs are not aligned (they really should be though) */ - CopyMem(&start, &entry->StartingLBA, sizeof(start)); - CopyMem(&end, &entry->EndingLBA, sizeof(end)); + memcpy(&start, &entry->StartingLBA, sizeof(start)); + memcpy(&end, &entry->EndingLBA, sizeof(end)); if (end < start) /* Bogus? */ continue; @@ -138,7 +138,7 @@ static EFI_STATUS try_gpt( ret_hd->PartitionSize = end - start + 1; ret_hd->MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; ret_hd->SignatureType = SIGNATURE_TYPE_GUID; - CopyMem(ret_hd->Signature, &entry->UniquePartitionGUID, sizeof(ret_hd->Signature)); + memcpy(ret_hd->Signature, &entry->UniquePartitionGUID, sizeof(ret_hd->Signature)); return EFI_SUCCESS; } @@ -227,7 +227,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p /* Patch in the data we found */ EFI_DEVICE_PATH *xboot_path = ASSERT_SE_PTR(DuplicateDevicePath(partition_path)); - CopyMem((UINT8 *) xboot_path + ((UINT8 *) part_node - (UINT8 *) partition_path), &hd, sizeof(hd)); + memcpy((UINT8 *) xboot_path + ((UINT8 *) part_node - (UINT8 *) partition_path), &hd, sizeof(hd)); *ret_device_path = xboot_path; return EFI_SUCCESS; } diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 59d63e8e5d..bb9e779dd2 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -77,7 +77,6 @@ #define static_assert _Static_assert #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); }) - #define memcpy(a, b, c) CopyMem((a), (b), (c)) #define free(a) FreePool(a) #endif diff --git a/src/fundamental/sha256.c b/src/fundamental/sha256.c index 0577a24920..6fcb37a7d9 100644 --- a/src/fundamental/sha256.c +++ b/src/fundamental/sha256.c @@ -23,8 +23,10 @@ /* Written by Ulrich Drepper , 2007. */ -#ifndef SD_BOOT -#include +#ifdef SD_BOOT +# include "efi-string.h" +#else +# include #endif #include "macro-fundamental.h" diff --git a/src/fundamental/string-util-fundamental.h b/src/fundamental/string-util-fundamental.h index 01df4ce17a..8048a07f73 100644 --- a/src/fundamental/string-util-fundamental.h +++ b/src/fundamental/string-util-fundamental.h @@ -2,31 +2,30 @@ #pragma once #ifdef SD_BOOT -#include -#include +# include +# include +# include "efi-string.h" #else -#include +# include #endif #include "macro-fundamental.h" #ifdef SD_BOOT -#define strlen(a) StrLen((a)) -#define strcmp(a, b) StrCmp((a), (b)) -#define strncmp(a, b, n) StrnCmp((a), (b), (n)) -#define strcasecmp(a, b) StriCmp((a), (b)) -#define STR_C(str) (L ## str) -#define memcmp(a, b, n) CompareMem(a, b, n) +# define strlen strlen16 +# define strcmp strcmp16 +# define strncmp strncmp16 +# define strcasecmp strcasecmp16 +# define strncasecmp strncasecmp16 +# define STR_C(str) (L ## str) #else -#define STR_C(str) (str) +# define STR_C(str) (str) #endif #define streq(a,b) (strcmp((a),(b)) == 0) #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) #define strcaseeq(a,b) (strcasecmp((a),(b)) == 0) -#ifndef SD_BOOT #define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0) -#endif static inline sd_int strcmp_ptr(const sd_char *a, const sd_char *b) { if (a && b)