]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/kvm/x86: Add formatted printing utility using during EFI boot
authorKha Dinh <khadinh@g.skku.edu>
Wed, 18 Oct 2023 07:29:21 +0000 (07:29 +0000)
committerKha Dinh <khadinh@g.skku.edu>
Thu, 26 Oct 2023 05:06:41 +0000 (05:06 +0000)
The current crash printing is somewhat limited as it cannot print
variables.
This commit refactor EFI debug printing. It adds a printf-like
utility for easier time debugging, rename some functions to be
more consistent with the rest of the code base.
Also, debug printing in EFI now depends on `libukdebug`, instead of
a dedicated option.

Signed-off-by: Kha Dinh <khadinh@g.skku.edu>
plat/kvm/Config.uk
plat/kvm/efi.c

index 8f7147e064b53b58bce75ae3dd6b27432ef43ab4..30e3a238bf62b382efdf9003ada389c57e6fbb9b 100644 (file)
@@ -58,10 +58,6 @@ endchoice
 
 if KVM_BOOT_PROTO_EFI_STUB
 
-config KVM_BOOT_PROTO_EFI_STUB_DEBUG
-       bool "Enable EFI stub crash messages"
-       default n
-
 config KVM_BOOT_PROTO_EFI_STUB_CMDLINE_FNAME
        string "Name of the command line arguments file"
        default "$(UK_NAME).cmdl"
index 13334052a0705fd34b97af315c9c2f8db67f9948..836bb3d2f18fe601a43f80d02bc8421dd7e06319 100644 (file)
@@ -3,6 +3,7 @@
  * Licensed under the BSD-3-Clause License (the "License").
  * You may not use this file except in compliance with the License.
  */
+#include <uk/libid.h>
 #include <kvm/efi.h>
 #include <uk/arch/paging.h>
 #include <uk/plat/common/bootinfo.h>
@@ -16,6 +17,9 @@ static enum uk_efi_alloc_type uk_efi_alloc_type = UK_EFI_ALLOCATE_ANY_PAGES;
 #else  /* !CONFIG_HAVE_PAGING */
 static enum uk_efi_alloc_type uk_efi_alloc_type = UK_EFI_ALLOCATE_MAX_ADDRESS;
 #endif /* !CONFIG_HAVE_PAGING */
+#if CONFIG_LIBUKDEBUG_PRINTD
+#include <stdio.h>
+#endif /* CONFIG_LIBUKDEBUG_PRINTD */
 
 static struct uk_efi_runtime_services *uk_efi_rs;
 static struct uk_efi_boot_services *uk_efi_bs;
@@ -76,7 +80,7 @@ static __sz utf16_to_ascii(const char *str16, char *str, __sz max_len)
        return i + 1;
 }
 
-static void _uk_efi_crash(void)
+static void uk_efi_do_crash(void)
 {
        const char reset_data[] = "UK EFI SYSTEM CRASH";
 
@@ -84,22 +88,38 @@ static void _uk_efi_crash(void)
                                sizeof(reset_data), (void *)reset_data);
 }
 
-#ifdef CONFIG_KVM_BOOT_PROTO_EFI_STUB_DEBUG
-#define UK_EFI_MAX_CRASH_STR_LEN                               256
+#if CONFIG_LIBUKDEBUG_PRINTD
+#define UK_EFI_MAX_FMT_STR_LEN                                 256
+
+static void uk_efi_printf(const char *str, ...)
+{
+       char fmt_str[UK_EFI_MAX_FMT_STR_LEN];
+       char str_tmp[UK_EFI_MAX_FMT_STR_LEN];
+       __s16 str16[UK_EFI_MAX_FMT_STR_LEN];
+       va_list ap;
+
+       sprintf(fmt_str, "dbg: [%s] <%s @ %4u> %s\r", uk_libname_self(),
+               STRINGIFY(__BASENAME__), __LINE__, str);
+
+       va_start(ap, str);
+       vsprintf(str_tmp, fmt_str, ap);
+       va_end(ap);
+
+       ascii_to_utf16(str_tmp, (char *)str16, UK_EFI_MAX_FMT_STR_LEN - 1);
+       uk_efi_st->con_out->output_string(uk_efi_st->con_out, str16);
+}
+
+#define uk_efi_pr_debug uk_efi_printf
 /* UEFI for proper \n, we must also use CRLF */
-#define uk_efi_crash(str)                                              \
-       do {                                                            \
-               __s16 str16[UK_EFI_MAX_CRASH_STR_LEN];                  \
-                                                                       \
-               ascii_to_utf16("[uk_efi]: "str"\r", (char *)str16,      \
-                              UK_EFI_MAX_CRASH_STR_LEN - 1);           \
-               uk_efi_st->con_out->output_string(uk_efi_st->con_out,   \
-                                                 str16);               \
-               _uk_efi_crash();                                        \
+#define UK_EFI_CRASH(...)                                      \
+       do {                                                    \
+               uk_efi_printf(__VA_ARGS__);                     \
+               uk_efi_do_crash();                              \
        } while (0)
 #else
-#define uk_efi_crash(str)                                      _uk_efi_crash()
-#endif
+#define uk_efi_pr_debug(...)
+#define UK_EFI_CRASH(str)                                      uk_efi_do_crash()
+#endif /* CONFIG_LIBUKDEBUG_PRINTD */
 
 static void uk_efi_cls(void)
 {
@@ -216,7 +236,7 @@ static void uk_efi_get_mmap(struct uk_efi_mem_desc **map, uk_efi_uintn_t *map_sz
        status = uk_efi_bs->get_memory_map(map_sz, *map, &uk_efi_map_key,
                                           desc_sz, &desc_ver);
        if (unlikely(status != UK_EFI_BUFFER_TOO_SMALL))
-               uk_efi_crash("Failed to call initial dummy get_memory_map\n");
+               UK_EFI_CRASH("Failed to call initial dummy get_memory_map\n");
 
        /* Make sure the actual allocated buffer is bigger */
        *map_sz += *desc_sz * UK_EFI_SURPLUS_MEM_DESC_COUNT;
@@ -226,13 +246,13 @@ static void uk_efi_get_mmap(struct uk_efi_mem_desc **map, uk_efi_uintn_t *map_sz
                                           DIV_ROUND_UP(*map_sz, PAGE_SIZE),
                                           (uk_efi_paddr_t *)map);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to allocate memory for map\n");
+               UK_EFI_CRASH("Failed to allocate memory for map\n");
 
        /* Now we call it for real */
        status = uk_efi_bs->get_memory_map(map_sz, *map, &uk_efi_map_key,
                                           desc_sz, &desc_ver);
-       if unlikely((status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to get memory map\n");
+       if (unlikely(status != UK_EFI_SUCCESS))
+               UK_EFI_CRASH("Failed to get memory map\n");
 }
 
 /* Runtime Services memory regions in the Memory Attribute Table have a higher
@@ -278,7 +298,7 @@ static void uk_efi_rt_md_to_bi_mrds(struct ukplat_memregion_desc **rt_mrds,
                                          *rt_mrds_count * sizeof(**rt_mrds),
                                          (void **)rt_mrds);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to allocate memory for Memory Sub-region Descriptors\n");
+               UK_EFI_CRASH("Failed to allocate memory for Memory Sub-region Descriptors\n");
 
        /* Convert the EFI Runtime Services Memory descriptors to
         * ukplat_memregion_desc's
@@ -320,7 +340,7 @@ static void uk_efi_setup_bootinfo_mrds(struct ukplat_bootinfo *bi)
 #if defined(__X86_64__)
        rc = ukplat_memregion_list_insert_legacy_hi_mem(&bi->mrds);
        if (unlikely(rc < 0))
-               uk_efi_crash("Failed to insert legacy high memory region\n");
+               UK_EFI_CRASH("Failed to insert legacy high memory region\n");
 #endif
 
        /* Fetch the Runtime Services memory regions from the MAT */
@@ -328,13 +348,13 @@ static void uk_efi_setup_bootinfo_mrds(struct ukplat_bootinfo *bi)
        for (i = 0; i < rt_mrds_count; i++) {
                rc = ukplat_memregion_list_insert(&bi->mrds, &rt_mrds[i]);
                if (unlikely(rc < 0))
-                       uk_efi_crash("Failed to insert rt_mrd\n");
+                       UK_EFI_CRASH("Failed to insert rt_mrd\n");
        }
 
        /* We no longer need the list of Runtime Services memory regions */
        status = uk_efi_bs->free_pool(rt_mrds);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to free rt_mrds\n");
+               UK_EFI_CRASH("Failed to free rt_mrds\n");
 
        /* Get memory map through GetMemoryMap */
        uk_efi_get_mmap(&map_start, &map_sz, &desc_sz);
@@ -347,7 +367,7 @@ static void uk_efi_setup_bootinfo_mrds(struct ukplat_bootinfo *bi)
 
                rc = ukplat_memregion_list_insert(&bi->mrds,  &mrd);
                if (unlikely(rc < 0))
-                       uk_efi_crash("Failed to insert mrd\n");
+                       UK_EFI_CRASH("Failed to insert mrd\n");
        }
 
        ukplat_memregion_list_coalesce(&bi->mrds);
@@ -355,7 +375,7 @@ static void uk_efi_setup_bootinfo_mrds(struct ukplat_bootinfo *bi)
 #if defined(__X86_64__)
        rc = ukplat_memregion_alloc_sipi_vect();
        if (unlikely(rc))
-               uk_efi_crash("Failed to insert SIPI vector region\n");
+               UK_EFI_CRASH("Failed to insert SIPI vector region\n");
 #endif
 }
 
@@ -372,7 +392,7 @@ static struct uk_efi_ld_img_hndl *uk_efi_get_uk_img_hndl(void)
                                            UK_EFI_LOADED_IMAGE_PROTOCOL_GUID,
                                            (void **)&uk_img_hndl);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to handle loaded image protocol\n");
+               UK_EFI_CRASH("Failed to handle loaded image protocol\n");
 
        return uk_img_hndl;
 }
@@ -393,7 +413,7 @@ static void uk_efi_read_file(uk_efi_hndl_t dev_h, const char *file_name,
                                            UK_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
                                            &sfs_proto);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to handle Simple Filesystem Protocol\n");
+               UK_EFI_CRASH("Failed to handle Simple Filesystem Protocol\n");
 
        /* For each block device that supports FAT12/16/32 firmware
         * automatically creates handles for it. So now we basically open
@@ -401,19 +421,19 @@ static void uk_efi_read_file(uk_efi_hndl_t dev_h, const char *file_name,
         */
        status = sfs_proto->open_volume(sfs_proto, &volume);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to open Volume\n");
+               UK_EFI_CRASH("Failed to open Volume\n");
 
        /* UEFI only knows UTF-16 */
        len16 = ascii_to_utf16(file_name, (char *)file_name16,
                               UK_EFI_MAXPATHLEN - 1);
        if (unlikely(len16 > UK_EFI_MAXPATHLEN))
-               uk_efi_crash("File path too long\n");
+               UK_EFI_CRASH("File path too long\n");
 
        status = volume->open(volume, &file_hndl, file_name16,
                              UK_EFI_FILE_MODE_READ,
                              UK_EFI_FILE_READ_ONLY | UK_EFI_FILE_HIDDEN);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to open file\n");
+               UK_EFI_CRASH("Failed to open file\n");
 
        /* Just like GetMemoryMap, we first need to do a dummy call */
        file_info_len = 0;
@@ -421,17 +441,17 @@ static void uk_efi_read_file(uk_efi_hndl_t dev_h, const char *file_name,
        status = file_hndl->get_info(file_hndl, UK_EFI_FILE_INFO_ID_GUID,
                                     &file_info_len, file_info);
        if (unlikely(status != UK_EFI_BUFFER_TOO_SMALL))
-               uk_efi_crash("Dummy call to get_info failed\n");
+               UK_EFI_CRASH("Dummy call to get_info failed\n");
 
        status = uk_efi_bs->allocate_pool(UK_EFI_LOADER_DATA, file_info_len,
                                          (void **)&file_info);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to allocate memory for file_info\n");
+               UK_EFI_CRASH("Failed to allocate memory for file_info\n");
 
        status = file_hndl->get_info(file_hndl, UK_EFI_FILE_INFO_ID_GUID,
                                     &file_info_len, file_info);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to get file_info\n");
+               UK_EFI_CRASH("Failed to get file_info\n");
 
        *len = file_info->file_size;
        *buf = (char *)uk_efi_alloc_max_paddr;
@@ -440,15 +460,15 @@ static void uk_efi_read_file(uk_efi_hndl_t dev_h, const char *file_name,
                                           DIV_ROUND_UP(*len, PAGE_SIZE),
                                           (uk_efi_paddr_t *)buf);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to allocate memory for file contents\n");
+               UK_EFI_CRASH("Failed to allocate memory for file contents\n");
 
        status = file_hndl->read(file_hndl, len, *buf);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to read file\n");
+               UK_EFI_CRASH("Failed to read file\n");
 
        status = uk_efi_bs->free_pool(file_info);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to free file_info\n");
+               UK_EFI_CRASH("Failed to free file_info\n");
 
        (*buf)[*len] = '\0';
 }
@@ -479,12 +499,12 @@ static void uk_efi_setup_bootinfo_cmdl(struct ukplat_bootinfo *bi)
                                                   DIV_ROUND_UP(len, PAGE_SIZE),
                                                   (uk_efi_paddr_t *)&cmdl);
                if (unlikely(status != UK_EFI_SUCCESS))
-                       uk_efi_crash("Failed to allocate memory for cmdl\n");
+                       UK_EFI_CRASH("Failed to allocate memory for cmdl\n");
 
                /* Update actual size */
                len = utf16_to_ascii(uk_img_hndl->load_options, cmdl, len - 1);
                if (unlikely(len == __SZ_MAX))
-                       uk_efi_crash("Conversion from UTF-16 to ASCII of cmdl "
+                       UK_EFI_CRASH("Conversion from UTF-16 to ASCII of cmdl "
                                     "overflowed. This shouldn't be possible\n");
        } else if (sizeof(EFI_STUB_CMDLINE_FNAME) > 1) {
                uk_efi_read_file(uk_img_hndl->device_handle,
@@ -502,7 +522,7 @@ static void uk_efi_setup_bootinfo_cmdl(struct ukplat_bootinfo *bi)
        mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_MAP;
        rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
        if (unlikely(rc < 0))
-               uk_efi_crash("Failed to insert cmdl mrd\n");
+               UK_EFI_CRASH("Failed to insert cmdl mrd\n");
 
        bi->cmdline = (__u64)cmdl;
        bi->cmdline_len = len;
@@ -532,7 +552,7 @@ static void uk_efi_setup_bootinfo_initrd(struct ukplat_bootinfo *bi)
        mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_MAP;
        rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
        if (unlikely(rc < 0))
-               uk_efi_crash("Failed to insert initrd mrd\n");
+               UK_EFI_CRASH("Failed to insert initrd mrd\n");
 }
 
 static void uk_efi_setup_bootinfo_dtb(struct ukplat_bootinfo *bi)
@@ -559,7 +579,7 @@ static void uk_efi_setup_bootinfo_dtb(struct ukplat_bootinfo *bi)
        mrd.flags = UKPLAT_MEMRF_READ | UKPLAT_MEMRF_MAP;
        rc = ukplat_memregion_list_insert(&bi->mrds, &mrd);
        if (unlikely(rc < 0))
-               uk_efi_crash("Failed to insert dtb mrd\n");
+               UK_EFI_CRASH("Failed to insert dtb mrd\n");
 
        bi->dtb = (__u64)dtb;
 }
@@ -572,7 +592,7 @@ static void uk_efi_setup_bootinfo(void)
 
        bi = ukplat_bootinfo_get();
        if (unlikely(!bi))
-               uk_efi_crash("Failed to get bootinfo\n");
+               UK_EFI_CRASH("Failed to get bootinfo\n");
 
        memcpy(bi->bootloader, bl, sizeof(bl));
        memcpy(bi->bootprotocol, bp, sizeof(bp));
@@ -615,7 +635,7 @@ static void uk_efi_reset_attack_mitigation_enable(void)
        if (status == UK_EFI_UNSUPPORTED || status == UK_EFI_NOT_FOUND)
                return;
        else if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to get MemoryOverwriteRequestControl variable\n");
+               UK_EFI_CRASH("Failed to get MemoryOverwriteRequestControl variable\n");
 
        status = uk_efi_rs->set_variable((__s16 *)var_name,
                                         MEMORY_ONLY_RESET_CONTROL_GUID,
@@ -624,7 +644,7 @@ static void uk_efi_reset_attack_mitigation_enable(void)
                                         UK_EFI_VARIABLE_RUNTIME_ACCESS,
                                         sizeof(enable), &enable);
        if (unlikely(status != UK_EFI_SUCCESS))
-               uk_efi_crash("Failed to enable reset attack mitigation\n");
+               UK_EFI_CRASH("Failed to enable reset attack mitigation\n");
 #endif
 }