const char16_t *fname,
const void *contents,
size_t contents_size,
- const char *target_dir_prefix,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t *inode_counter,
void **cpio_buffer,
size_t *cpio_buffer_size) {
assert(fname);
assert(contents || contents_size == 0);
- assert(target_dir_prefix);
+ assert(target);
assert(inode_counter);
assert(cpio_buffer);
assert(cpio_buffer_size);
l = 6 + 13*8 + 1 + 1; /* Fixed CPIO header size, slash separator, and NUL byte after the file name */
- target_dir_prefix_size = strlen8(target_dir_prefix);
+ target_dir_prefix_size = strlen8(target->directory);
if (l > SIZE_MAX - target_dir_prefix_size)
return EFI_OUT_OF_RESOURCES;
l += target_dir_prefix_size;
a = mempcpy(a, "070701", 6); /* magic ID */
- a = write_cpio_word(a, (*inode_counter)++); /* inode */
- a = write_cpio_word(a, access_mode | 0100000 /* = S_IFREG */); /* mode */
- a = write_cpio_word(a, 0); /* uid */
- a = write_cpio_word(a, 0); /* gid */
- a = write_cpio_word(a, 1); /* nlink */
+ a = write_cpio_word(a, (*inode_counter)++); /* inode */
+ a = write_cpio_word(a, target->access_mode | 0100000 /* = S_IFREG */); /* mode */
+ a = write_cpio_word(a, 0); /* uid */
+ a = write_cpio_word(a, 0); /* gid */
+ a = write_cpio_word(a, 1); /* nlink */
/* Note: we don't make any attempt to propagate the mtime here, for two reasons: it's a mess given
* that FAT usually is assumed to operate with timezoned timestamps, while UNIX does not. More
a = write_cpio_word(a, target_dir_prefix_size + fname_size + 2); /* fname size */
a = write_cpio_word(a, 0); /* "crc" */
- a = mempcpy(a, target_dir_prefix, target_dir_prefix_size);
+ a = mempcpy(a, target->directory, target_dir_prefix_size);
*(a++) = '/';
a = mangle_filename(a, fname);
}
static EFI_STATUS pack_cpio_prefix(
- const char *path,
- uint32_t dir_mode,
+ const CpioTarget *target,
uint32_t *inode_counter,
void **cpio_buffer,
size_t *cpio_buffer_size) {
EFI_STATUS err;
- assert(path);
+ assert(target);
assert(inode_counter);
assert(cpio_buffer);
assert(cpio_buffer_size);
* (similar to mkdir -p behaviour) all leading paths are created with 0555 access mode, only the
* final dir is created with the specified directory access mode. */
- for (const char *p = path;;) {
+ for (const char *p = target->directory;;) {
const char *e;
e = strchr8(p, '/');
if (e > p) {
_cleanup_free_ char *t = NULL;
- t = xstrndup8(path, e - path);
+ t = xstrndup8(target->directory, e - target->directory);
if (!t)
return EFI_OUT_OF_RESOURCES;
p = e + 1;
}
- return pack_cpio_dir(path, dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
+ return pack_cpio_dir(target->directory, target->dir_mode, inode_counter, cpio_buffer, cpio_buffer_size);
}
static EFI_STATUS pack_cpio_trailer(
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
- const char *target_dir_prefix,
- uint32_t dir_mode,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
EFI_STATUS err;
assert(loaded_image);
- assert(target_dir_prefix);
+ assert(target);
assert(ret_buffer);
if (!loaded_image->DeviceHandle)
/* 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. */
- err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+ err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to pack cpio prefix: %m");
err = pack_cpio_one(
items[i],
content, contentsize,
- target_dir_prefix,
- access_mode,
+ target,
&inode,
&buffer, &buffer_size);
if (err != EFI_SUCCESS)
EFI_STATUS pack_cpio_literal(
const void *data,
size_t data_size,
- const char *target_dir_prefix,
+ const CpioTarget *target,
const char16_t *target_filename,
- uint32_t dir_mode,
- uint32_t access_mode,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
EFI_STATUS err;
assert(data || data_size == 0);
- assert(target_dir_prefix);
+ assert(target);
assert(target_filename);
assert(ret_buffer);
/* 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. */
- err = pack_cpio_prefix(target_dir_prefix, dir_mode, &inode, &buffer, &buffer_size);
+ err = pack_cpio_prefix(target, &inode, &buffer, &buffer_size);
if (err != EFI_SUCCESS)
return log_error_status(err, "Failed to pack cpio prefix: %m");
err = pack_cpio_one(
target_filename,
data, data_size,
- target_dir_prefix,
- access_mode,
+ target,
&inode,
&buffer, &buffer_size);
if (err != EFI_SUCCESS)
*ret_buffer = IOVEC_MAKE(TAKE_PTR(buffer), buffer_size);
return EFI_SUCCESS;
}
+
+/* The following are canonical definitions of the various cpio target directories we place resources in. We
+ * define them here in a single canonical list of targets because we need to reuse them at various places
+ * (well, some of them at least), and we don't want the access modes to deviate slightly on each use. */
+
+const CpioTarget cpio_target_credentials = {
+ .directory = ".extra/credentials",
+ .dir_mode = 0500,
+ .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_global_credentials = {
+ .directory = ".extra/global_credentials",
+ .dir_mode = 0500,
+ .access_mode = 0400,
+};
+
+const CpioTarget cpio_target_sysext = {
+ .directory = ".extra/sysext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_sysext = {
+ .directory = ".extra/global_sysext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_confext = {
+ .directory = ".extra/confext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_global_confext = {
+ .directory = ".extra/global_confext",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta = {
+ .directory = ".extra",
+ .dir_mode = 0555,
+ .access_mode = 0444,
+};
+
+const CpioTarget cpio_target_meta_secret = {
+ .directory = ".extra",
+ .dir_mode = 0555,
+ .access_mode = 0400,
+};
#include "efi.h"
#include "proto/loaded-image.h"
+typedef struct CpioTarget {
+ const char *directory; /* Path to directory where to place resources */
+ uint32_t dir_mode; /* Access mode for the directory */
+ uint32_t access_mode; /* Access mode for the files in the directory */
+} CpioTarget;
+
EFI_STATUS pack_cpio(
EFI_LOADED_IMAGE_PROTOCOL *loaded_image,
const char16_t *dropin_dir,
const char16_t *match_suffix,
const char16_t *exclude_suffix,
- const char *target_dir_prefix,
- uint32_t dir_mode,
- uint32_t access_mode,
+ const CpioTarget *target,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
EFI_STATUS pack_cpio_literal(
const void *data,
size_t data_size,
- const char *target_dir_prefix,
+ const CpioTarget *target,
const char16_t *target_filename,
- uint32_t dir_mode,
- uint32_t access_mode,
uint32_t tpm_pcr,
const char16_t *tpm_description,
struct iovec *ret_buffer,
bool *ret_measured);
+
+extern const CpioTarget cpio_target_credentials;
+extern const CpioTarget cpio_target_global_credentials;
+extern const CpioTarget cpio_target_sysext;
+extern const CpioTarget cpio_target_global_sysext;
+extern const CpioTarget cpio_target_confext;
+extern const CpioTarget cpio_target_global_confext;
+extern const CpioTarget cpio_target_meta;
+extern const CpioTarget cpio_target_meta_secret;
/* dropin_dir= */ NULL,
u".cred",
/* exclude_suffix= */ NULL,
- ".extra/credentials",
- /* dir_mode= */ 0500,
- /* access_mode= */ 0400,
+ &cpio_target_credentials,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Credentials initrd",
initrds + INITRD_CREDENTIAL,
u"\\loader\\credentials",
u".cred",
/* exclude_suffix= */ NULL,
- ".extra/global_credentials",
- /* dir_mode= */ 0500,
- /* access_mode= */ 0400,
+ &cpio_target_global_credentials,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Global credentials initrd",
initrds + INITRD_GLOBAL_CREDENTIAL,
/* dropin_dir= */ NULL,
u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
u".confext.raw", /* … but then exclude *.confext.raw again */
- ".extra/sysext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_sysext,
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
u"System extension initrd",
initrds + INITRD_SYSEXT,
u"\\loader\\extensions",
u".raw", /* as above */
u".confext.raw",
- ".extra/global_sysext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_global_sysext,
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
u"Global system extension initrd",
initrds + INITRD_GLOBAL_SYSEXT,
/* dropin_dir= */ NULL,
u".confext.raw",
/* exclude_suffix= */ NULL,
- ".extra/confext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_confext,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Configuration extension initrd",
initrds + INITRD_CONFEXT,
u"\\loader\\extensions",
u".confext.raw",
/* exclude_suffix= */ NULL,
- ".extra/global_confext",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
+ &cpio_target_global_confext,
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
u"Global configuration extension initrd",
initrds + INITRD_GLOBAL_CONFEXT,
(void) pack_cpio_literal(
(const uint8_t*) loaded_image->ImageBase + sections[t->section].memory_offset,
sections[t->section].memory_size,
- ".extra",
+ &cpio_target_meta,
t->filename,
- /* dir_mode= */ 0555,
- /* access_mode= */ 0444,
/* tpm_pcr= */ UINT32_MAX,
/* tpm_description= */ NULL,
initrds + t->initrd_index,
(void) pack_cpio_literal(
boot_secret,
BOOT_SECRET_SIZE,
- ".extra",
+ &cpio_target_meta_secret,
u"boot-secret",
- /* dir_mode= */ 0555,
- /* access_mode= */ 0400,
/* tpm_pcr= */ UINT32_MAX,
/* tpm_description= */ NULL,
initrds + INITRD_BOOT_SECRET,