]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Fix integer format specifiers
authorJan Janssen <medhefgo@web.de>
Wed, 16 Feb 2022 11:28:20 +0000 (12:28 +0100)
committerJan Janssen <medhefgo@web.de>
Wed, 13 Apr 2022 21:06:26 +0000 (23:06 +0200)
gnu-efi only knows two sizes for formatting integers: 32bit without
a length prefix and 64bit with 'l' prefix. Provide a PRI-style format
specifier for (U)INTN so that Print() can read the right amount of
bytes instead of printing garbage or worse.

src/boot/efi/boot.c
src/boot/efi/drivers.c
src/boot/efi/stub.c
src/boot/efi/util.c
src/boot/efi/util.h

index 96e56a7839118836b3ec317d8b5a59f7b4604479..ca43f0073982ec405619efcd0d9eb0642051adb5 100644 (file)
@@ -493,7 +493,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
             Print(L"           secure boot: %s (%s)\n", yes_no(IN_SET(secure, SECURE_BOOT_USER, SECURE_BOOT_DEPLOYED)), secure_boot_mode_to_string(secure));
           ps_bool(L"                  shim: %s\n",      shim_loaded());
           ps_bool(L"                   TPM: %s\n",      tpm_present());
-            Print(L"          console mode: %d/%d (%lux%lu @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - 1LL, x_max, y_max, screen_width, screen_height);
+            Print(L"          console mode: %d/%ld (%" PRIuN L"x%" PRIuN L" @%ux%u)\n", ST->ConOut->Mode->Mode, ST->ConOut->Mode->MaxMode - INT64_C(1), x_max, y_max, screen_width, screen_height);
 
         if (!ps_continue())
                 return;
@@ -506,7 +506,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
         case TIMEOUT_MENU_HIDDEN:
             Print(L"               timeout: menu-hidden\n"); break;
         default:
-            Print(L"               timeout: %lu s\n", config->timeout_sec_config);
+            Print(L"               timeout: %u s\n", config->timeout_sec_config);
         }
 
         switch (config->timeout_sec_efivar) {
@@ -517,7 +517,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
         case TIMEOUT_MENU_HIDDEN:
             Print(L"     timeout (EFI var): menu-hidden\n"); break;
         default:
-            Print(L"     timeout (EFI var): %lu s\n", config->timeout_sec_efivar);
+            Print(L"     timeout (EFI var): %u s\n", config->timeout_sec_efivar);
         }
 
         ps_string(L"               default: %s\n", config->entry_default_config);
@@ -552,7 +552,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
         for (UINTN i = 0; i < config->entry_count; i++) {
                 ConfigEntry *entry = config->entries[i];
 
-                    Print(L"  config entry: %lu/%lu\n", i + 1, config->entry_count);
+                    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);
@@ -568,7 +568,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) {
 
                   ps_bool(L"counting boots: %s\n", entry->tries_left != UINTN_MAX);
                 if (entry->tries_left != UINTN_MAX) {
-                    Print(L"         tries: %lu done, %lu left\n", entry->tries_done, entry->tries_left);
+                    Print(L"         tries: %" PRIuN L" done, %" PRIuN L" left\n", entry->tries_done, entry->tries_left);
                     Print(L"  current path: %s\\%s\n",  entry->path, entry->current_name);
                     Print(L"     next path: %s\\%s\n",  entry->path, entry->next_name);
                 }
@@ -920,10 +920,14 @@ static BOOLEAN menu_run(
                         break;
 
                 case KEYPRESS(0, 0, 'v'):
-                        status = xpool_print(L"systemd-boot " GIT_VERSION " (" EFI_MACHINE_TYPE_NAME "), "
-                                             L"UEFI Specification %d.%02d, Vendor %s %d.%02d",
-                                             ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff,
-                                             ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+                        status = xpool_print(
+                                        L"systemd-boot " GIT_VERSION L" (" EFI_MACHINE_TYPE_NAME L"), "
+                                        L"UEFI Specification %u.%02u, Vendor %s %u.%02u",
+                                        ST->Hdr.Revision >> 16,
+                                        ST->Hdr.Revision & 0xffff,
+                                        ST->FirmwareVendor,
+                                        ST->FirmwareRevision >> 16,
+                                        ST->FirmwareRevision & 0xffff);
                         break;
 
                 case KEYPRESS(0, 0, 'p'):
@@ -1362,7 +1366,7 @@ good:
         prefix = xstrdup(file);
         prefix[i] = 0;
 
-        entry->next_name = xpool_print(L"%s+%u-%u%s", prefix, next_left, next_done, suffix ?: L"");
+        entry->next_name = xpool_print(L"%s+%" PRIuN L"-%" PRIuN L"%s", prefix, next_left, next_done, suffix ?: L"");
 }
 
 static void config_entry_bump_counters(ConfigEntry *entry, EFI_FILE *root_dir) {
@@ -2074,7 +2078,7 @@ static EFI_STATUS boot_windows_bitlocker(void) {
                 CHAR16 name[sizeof(L"Boot0000")];
                 UINTN buf_size;
 
-                SPrint(name, sizeof(name), L"Boot%04x", boot_order[i]);
+                SPrint(name, sizeof(name), L"Boot%04x", (UINT32) boot_order[i]);
                 err = efivar_get_raw(EFI_GLOBAL_GUID, name, &buf, &buf_size);
                 if (EFI_ERROR(err))
                         continue;
@@ -2458,10 +2462,10 @@ static void export_variables(
         efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
         efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, 0);
 
-        infostr = xpool_print(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+        infostr = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
         efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, 0);
 
-        typestr = xpool_print(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+        typestr = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
         efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, 0);
 
         (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, 0);
index 376745f52984a4443a9b457b7931a645b7f5bc3e..2ff87261dabbf4666bd13d4b7939590cbfc4a8d6 100644 (file)
@@ -71,7 +71,7 @@ static EFI_STATUS reconnect(void) {
                   if (err == EFI_NOT_FOUND) /* No drivers for this handle */
                           continue;
                   if (EFI_ERROR(err))
-                          log_error_status_stall(err, L"Failed to reconnect handle %u, ignoring: %r", i, err);
+                          log_error_status_stall(err, L"Failed to reconnect handle %" PRIuN L", ignoring: %r", i, err);
           }
 
           return EFI_SUCCESS;
index 73d06de7f11cb80e94d389bd223da73b13eb5b12..40f615b2b363d1fdc370330e222a65fe4f094d32 100644 (file)
@@ -131,14 +131,14 @@ static void export_variables(EFI_LOADED_IMAGE *loaded_image) {
         /* if LoaderFirmwareInfo is not set, let's set it */
         if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
                 _cleanup_freepool_ CHAR16 *s = NULL;
-                s = xpool_print(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
+                s = xpool_print(L"%s %u.%02u", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
                 efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, 0);
         }
 
         /* ditto for LoaderFirmwareType */
         if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
                 _cleanup_freepool_ CHAR16 *s = NULL;
-                s = xpool_print(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
+                s = xpool_print(L"UEFI %u.%02u", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
                 efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, 0);
         }
 
index e6250207f68b9c4287df7cae3d21b500f6f15361..169add8680e9d7120468dd888c590254c1905a34 100644 (file)
@@ -57,7 +57,10 @@ EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UI
         assert(vendor);
         assert(name);
 
-        SPrint(str, ELEMENTSOF(str), L"%u", i);
+        /* Note that SPrint has no native sized length specifier and will always use ValueToString()
+         * regardless of what sign we tell it to use. Therefore, UINTN_MAX will come out as -1 on
+         * 64bit machines. */
+        ValueToString(str, FALSE, i);
         return efivar_set(vendor, name, str, flags);
 }
 
@@ -236,7 +239,8 @@ void efivar_set_time_usec(const EFI_GUID *vendor, const CHAR16 *name, UINT64 use
         if (usec == 0)
                 return;
 
-        SPrint(str, ELEMENTSOF(str), L"%ld", usec);
+        /* See comment on ValueToString in efivar_set_uint_string(). */
+        ValueToString(str, FALSE, usec);
         efivar_set(vendor, name, str, 0);
 }
 
index 93dd2da566fc238ea15c63ea1e9d8f768363f1c4..c45374a08ebe7f6836c0d47d1b731fdd45ee8746 100644 (file)
 #define UINT64_MAX ((UINT64) -1)
 #endif
 
+/* gnu-efi format specifiers for integers are fixed to either 64bit with 'l' and 32bit without a size prefix.
+ * We rely on %u/%d/%x to format regular ints, so ensure the size is what we expect. At the same time, we also
+ * need specifiers for (U)INTN which are native (pointer) sized. */
+assert_cc(sizeof(int) == sizeof(UINT32));
+#if __SIZEOF_POINTER__ == 4
+#  define PRIuN L"u"
+#  define PRIiN L"d"
+#elif __SIZEOF_POINTER__ == 8
+#  define PRIuN L"lu"
+#  define PRIiN L"ld"
+#else
+#  error "Unexpected pointer size"
+#endif
+
 #define xnew_alloc(type, n, alloc)                                           \
         ({                                                                   \
                 UINTN _alloc_size;                                           \
@@ -146,7 +160,7 @@ void debug_break(void);
 extern UINT8 _text, _data;
 /* Report the relocated position of text and data sections so that a debugger
  * can attach to us. See debug-sd-boot.sh for how this can be done. */
-#  define debug_hook(identity) Print(identity L"@0x%x,0x%x\n", &_text, &_data)
+#  define debug_hook(identity) Print(identity L"@0x%lx,0x%lx\n", POINTER_TO_PHYSICAL_ADDRESS(&_text), POINTER_TO_PHYSICAL_ADDRESS(&_data))
 #else
 #  define debug_hook(identity)
 #endif