]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: add DevicetreeAddon structure
authorLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 09:18:51 +0000 (11:18 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 15:09:45 +0000 (17:09 +0200)
Instead of keeping three parallel arrays of dt base, dt size and dt
filename, just introduce a proper structure and use an array of that,
greatly simplifying DT handling.

src/boot/efi/stub.c

index 2bea86ff99adc10068beb408aabebdaec867b4da..363184ef10e83c84d113228015276672b3ac65cf 100644 (file)
@@ -312,100 +312,90 @@ static void cmdline_append_and_measure_addons(
         *cmdline_append = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", merged);
 }
 
-static void dtb_install_addons(
+typedef struct DevicetreeAddon {
+        char16_t *filename;
+        struct iovec blob;
+} DevicetreeAddon;
+
+static void devicetree_addon_done(DevicetreeAddon *a) {
+        assert(a);
+
+        a->filename = mfree(a->filename);
+        iovec_done(&a->blob);
+}
+
+static void devicetree_addon_free_many(DevicetreeAddon *a, size_t n) {
+        assert(a || n == 0);
+
+        FOREACH_ARRAY(i, a, n)
+                devicetree_addon_done(i);
+
+        free(a);
+}
+
+static void install_addon_devicetrees(
                 struct devicetree_state *dt_state,
-                void **dt_bases,
-                size_t *dt_sizes,
-                char16_t **dt_filenames,
-                size_t n_dts,
+                DevicetreeAddon *addons,
+                size_t n_addons,
                 int *ret_parameters_measured) {
 
         int parameters_measured = -1;
         EFI_STATUS err;
 
         assert(dt_state);
-        assert(n_dts == 0 || (dt_bases && dt_sizes && dt_filenames));
+        assert(addons || n_addons == 0);
         assert(ret_parameters_measured);
 
-        for (size_t i = 0; i < n_dts; ++i) {
-                err = devicetree_install_from_memory(dt_state, dt_bases[i], dt_sizes[i]);
-                if (err != EFI_SUCCESS)
+        FOREACH_ARRAY(a, addons, n_addons) {
+                err = devicetree_install_from_memory(dt_state, a->blob.iov_base, a->blob.iov_len);
+                if (err != EFI_SUCCESS) {
                         log_error_status(err, "Error loading addon devicetree, ignoring: %m");
-                else {
-                        bool m = false;
+                        continue;
+                }
 
-                        err = tpm_log_tagged_event(
+                bool m = false;
+                err = tpm_log_tagged_event(
+                                TPM2_PCR_KERNEL_CONFIG,
+                                POINTER_TO_PHYSICAL_ADDRESS(a->blob.iov_base),
+                                a->blob.iov_len,
+                                DEVICETREE_ADDON_EVENT_TAG_ID,
+                                a->filename,
+                                &m);
+                if (err != EFI_SUCCESS)
+                        return (void) log_error_status(
+                                        err,
+                                        "Unable to extend PCR %i with DTB addon '%ls': %m",
                                         TPM2_PCR_KERNEL_CONFIG,
-                                        POINTER_TO_PHYSICAL_ADDRESS(dt_bases[i]),
-                                        dt_sizes[i],
-                                        DEVICETREE_ADDON_EVENT_TAG_ID,
-                                        dt_filenames[i],
-                                        &m);
-                        if (err != EFI_SUCCESS)
-                                return (void) log_error_status(
-                                                err,
-                                                "Unable to add measurement of DTB addon #%zu to PCR %i: %m",
-                                                i,
-                                                TPM2_PCR_KERNEL_CONFIG);
-
-                        combine_measured_flag(&parameters_measured, m);
-                }
+                                        a->filename);
+
+                combine_measured_flag(&parameters_measured, m);
         }
 
         *ret_parameters_measured = parameters_measured;
 }
 
-static void dt_bases_free(void **dt_bases, size_t n_dt) {
-        assert(dt_bases || n_dt == 0);
-
-        for (size_t i = 0; i < n_dt; ++i)
-                free(dt_bases[i]);
-
-        free(dt_bases);
-}
-
-static void dt_filenames_free(char16_t **dt_filenames, size_t n_dt) {
-        assert(dt_filenames || n_dt == 0);
-
-        for (size_t i = 0; i < n_dt; ++i)
-                free(dt_filenames[i]);
-
-        free(dt_filenames);
-}
-
 static EFI_STATUS load_addons(
                 EFI_HANDLE stub_image,
                 EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
                 const char16_t *prefix,
                 const char *uname,
                 char16_t **ret_cmdline,
-                void ***ret_dt_bases,
-                size_t **ret_dt_sizes,
-                char16_t ***ret_dt_filenames,
-                size_t *ret_n_dt) {
+                DevicetreeAddon **ret_devicetree_addons,
+                size_t *ret_n_devicetree_addons) {
 
-        _cleanup_free_ size_t *dt_sizes = NULL;
         _cleanup_(strv_freep) char16_t **items = NULL;
         _cleanup_(file_closep) EFI_FILE *root = NULL;
         _cleanup_free_ char16_t *cmdline = NULL;
-        size_t n_items = 0, n_allocated = 0, n_dt = 0;
-        char16_t **dt_filenames = NULL;
-        void **dt_bases = NULL;
+        size_t n_items = 0, n_allocated = 0;
         EFI_STATUS err;
 
         assert(stub_image);
         assert(loaded_image);
         assert(prefix);
-        assert(!!ret_dt_bases == !!ret_dt_sizes);
-        assert(!!ret_dt_bases == !!ret_n_dt);
-        assert(!!ret_dt_filenames == !!ret_n_dt);
 
         if (!loaded_image->DeviceHandle)
                 return EFI_SUCCESS;
 
-        CLEANUP_ARRAY(dt_bases, n_dt, dt_bases_free);
-        CLEANUP_ARRAY(dt_filenames, n_dt, dt_filenames_free);
-
         err = open_volume(loaded_image->DeviceHandle, &root);
         if (err == EFI_UNSUPPORTED)
                 /* Error will be unsupported if the bootloader doesn't implement the file system protocol on
@@ -425,6 +415,10 @@ static EFI_STATUS load_addons(
          * are not dependent on read order) */
         sort_pointer_array((void**) items, n_items, (compare_pointer_func_t) strcmp16);
 
+        DevicetreeAddon *dt_addons = NULL;
+        size_t n_dt_addons = 0;
+        CLEANUP_ARRAY(dt_addons, n_dt_addons, devicetree_addon_free_many);
+
         for (size_t i = 0; i < n_items; i++) {
                 PeSectionVector sections[ELEMENTSOF(unified_sections)] = {};
                 _cleanup_free_ EFI_DEVICE_PATH *addon_path = NULL;
@@ -489,36 +483,27 @@ static EFI_STATUS load_addons(
                         cmdline = xasprintf("%ls%ls%ls", strempty(tmp), isempty(tmp) ? u"" : u" ", extra16);
                 }
 
-                if (ret_dt_bases && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) {
-                        dt_sizes = xrealloc(dt_sizes,
-                                            n_dt * sizeof(size_t),
-                                            (n_dt + 1)  * sizeof(size_t));
-                        dt_sizes[n_dt] = sections[UNIFIED_SECTION_DTB].size;
-
-                        dt_bases = xrealloc(dt_bases,
-                                            n_dt * sizeof(void *),
-                                            (n_dt + 1) * sizeof(void *));
-                        dt_bases[n_dt] = xmemdup((uint8_t*)loaded_addon->ImageBase + sections[UNIFIED_SECTION_DTB].memory_offset,
-                                                 dt_sizes[n_dt]);
-
-                        dt_filenames = xrealloc(dt_filenames,
-                                                n_dt * sizeof(char16_t *),
-                                                (n_dt + 1) * sizeof(char16_t *));
-                        dt_filenames[n_dt] = xstrdup16(items[i]);
-
-                        ++n_dt;
+                if (ret_devicetree_addons && PE_SECTION_VECTOR_IS_SET(sections + UNIFIED_SECTION_DTB)) {
+                        dt_addons = xrealloc(dt_addons,
+                                            n_dt_addons * sizeof(size_t),
+                                            (n_dt_addons + 1)  * sizeof(size_t));
+
+                        dt_addons[n_dt_addons++] = (DevicetreeAddon) {
+                                .blob = {
+                                        .iov_base = xmemdup((const uint8_t*) loaded_addon->ImageBase + sections[UNIFIED_SECTION_DTB].memory_offset, sections[UNIFIED_SECTION_DTB].size),
+                                        .iov_len = sections[UNIFIED_SECTION_DTB].size,
+                                },
+                                .filename =  xstrdup16(items[i]),
+                        };
                 }
         }
 
-        if (ret_cmdline && !isempty(cmdline))
+        if (ret_cmdline)
                 *ret_cmdline = TAKE_PTR(cmdline);
-
-        if (ret_n_dt && n_dt > 0) {
-                *ret_dt_filenames = TAKE_PTR(dt_filenames);
-                *ret_dt_bases = TAKE_PTR(dt_bases);
-                *ret_dt_sizes = TAKE_PTR(dt_sizes);
-                *ret_n_dt = n_dt;
-        }
+        if (ret_devicetree_addons)
+                *ret_devicetree_addons = TAKE_PTR(dt_addons);
+        if (ret_n_devicetree_addons)
+                *ret_n_devicetree_addons = n_dt_addons;
 
         return EFI_SUCCESS;
 }
@@ -842,10 +827,8 @@ static void install_embedded_devicetree(
 
 static EFI_STATUS run(EFI_HANDLE image) {
         _cleanup_(initrds_free) struct iovec initrds[_INITRD_MAX] = {};
-        void **dt_bases_addons_global = NULL, **dt_bases_addons_uki = NULL;
-        char16_t **dt_filenames_addons_global = NULL, **dt_filenames_addons_uki = NULL;
-        _cleanup_free_ size_t *dt_sizes_addons_global = NULL, *dt_sizes_addons_uki = NULL;
-        size_t n_dts_addons_global = 0, n_dts_addons_uki = 0;
+        DevicetreeAddon *dt_addons_global = NULL, *dt_addons_local = NULL;
+        size_t n_dt_addons_global = 0, n_dt_addons_local = 0;
         _cleanup_(devicetree_cleanup) struct devicetree_state dt_state = {};
         EFI_LOADED_IMAGE_PROTOCOL *loaded_image;
         PeSectionVector sections[ELEMENTSOF(unified_sections)] = {};
@@ -868,13 +851,11 @@ static EFI_STATUS run(EFI_HANDLE image) {
                 return log_error_status(err, "Unable to locate embedded .linux section: %m");
         }
 
-        CLEANUP_ARRAY(dt_bases_addons_global, n_dts_addons_global, dt_bases_free);
-        CLEANUP_ARRAY(dt_bases_addons_uki, n_dts_addons_uki, dt_bases_free);
-        CLEANUP_ARRAY(dt_filenames_addons_global, n_dts_addons_global, dt_filenames_free);
-        CLEANUP_ARRAY(dt_filenames_addons_uki, n_dts_addons_uki, dt_filenames_free);
-
         lookup_uname(loaded_image, sections, &uname);
 
+        CLEANUP_ARRAY(dt_addons_global, n_dt_addons_local, devicetree_addon_free_many);
+        CLEANUP_ARRAY(dt_addons_local, n_dt_addons_local, devicetree_addon_free_many);
+
         /* Now that we have the UKI sections loaded, also load global first and then local (per-UKI)
          * addons. The data is loaded at once, and then used later. */
         err = load_addons(
@@ -883,10 +864,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
                         u"\\loader\\addons",
                         uname,
                         &cmdline_addons_global,
-                        &dt_bases_addons_global,
-                        &dt_sizes_addons_global,
-                        &dt_filenames_addons_global,
-                        &n_dts_addons_global);
+                        &dt_addons_global,
+                        &n_dt_addons_global);
         if (err != EFI_SUCCESS)
                 log_error_status(err, "Error loading global addons, ignoring: %m");
 
@@ -899,10 +878,8 @@ static EFI_STATUS run(EFI_HANDLE image) {
                                 dropin_dir,
                                 uname,
                                 &cmdline_addons_uki,
-                                &dt_bases_addons_uki,
-                                &dt_sizes_addons_uki,
-                                &dt_filenames_addons_uki,
-                                &n_dts_addons_uki);
+                                &dt_addons_local,
+                                &n_dt_addons_local);
                 if (err != EFI_SUCCESS)
                         log_error_status(err, "Error loading UKI-specific addons, ignoring: %m");
         }
@@ -945,20 +922,9 @@ static EFI_STATUS run(EFI_HANDLE image) {
         install_embedded_devicetree(loaded_image, sections, &dt_state);
 
         int dtb_measured;
-        dtb_install_addons(&dt_state,
-                           dt_bases_addons_global,
-                           dt_sizes_addons_global,
-                           dt_filenames_addons_global,
-                           n_dts_addons_global,
-                           &dtb_measured);
+        install_addon_devicetrees(&dt_state, dt_addons_global, n_dt_addons_global, &dtb_measured);
         combine_measured_flag(&parameters_measured, dtb_measured);
-
-        dtb_install_addons(&dt_state,
-                           dt_bases_addons_uki,
-                           dt_sizes_addons_uki,
-                           dt_filenames_addons_uki,
-                           n_dts_addons_uki,
-                           &dtb_measured);
+        install_addon_devicetrees(&dt_state, dt_addons_local, n_dt_addons_local, &dtb_measured);
         combine_measured_flag(&parameters_measured, dtb_measured);
 
         export_pcr_variables(sections_measured, parameters_measured, sysext_measured, confext_measured);