This is an attempt to fix #42307, but should be a good thing anyway.
Related: #42307
* keep the GUID definitions in line with the UEFI spec. */
#define EFI_GLOBAL_VARIABLE_GUID EFI_GLOBAL_VARIABLE
#define EFI_FILE_INFO_GUID EFI_FILE_INFO_ID
+#define EFI_FILE_SYSTEM_INFO_GUID EFI_FILE_SYSTEM_INFO_ID
#define EFI_CUSTOM_MODE_ENABLE_GUID \
GUID_DEF(0xc076ec0c, 0x7028, 0x4399, 0xa0, 0x72, 0x71, 0xee, 0x5c, 0x44, 0x8b, 0x9f)
GUID_DEF(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
#define EFI_FILE_INFO_ID \
GUID_DEF(0x009576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+#define EFI_FILE_SYSTEM_INFO_ID \
+ GUID_DEF(0x009576e93, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
#define EFI_FILE_MODE_READ 0x0000000000000001U
#define EFI_FILE_MODE_WRITE 0x0000000000000002U
char16_t FileName[];
} EFI_FILE_INFO;
+typedef struct {
+ uint64_t Size;
+ bool ReadOnly;
+ uint64_t VolumeSize;
+ uint64_t FreeSpace;
+ uint32_t BlockSize;
+ char16_t VolumeLabel[];
+} EFI_FILE_SYSTEM_INFO;
+
/* Some broken firmware violates the EFI spec by still advancing the readdir
* position when returning EFI_BUFFER_TOO_SMALL, effectively skipping over any files when
* the buffer was too small. Therefore, we always start with a buffer that should handle FAT32
validate_sha256();
+ /* If the volume is read-only we cannot update the random seed, but if we cannot update it, then we
+ * really don't want to use it since it would be the same on every boot. */
+ bool volume_ro;
+ err = get_volume_ro(root_dir, &volume_ro);
+ if (err != EFI_SUCCESS)
+ log_debug_status(err, "Failed to determine if volume is read-only, assuming not: %m");
+ else if (volume_ro) {
+ log_debug("Volume is read-only, not updating random seed.");
+ return EFI_SUCCESS;
+ }
+
/* hash = LABEL || sizeof(input1) || input1 || ... || sizeof(inputN) || inputN */
sha256_init_ctx(&hash);
return EFI_SUCCESS;
}
+EFI_STATUS get_volume_ro(EFI_FILE *handle, bool *ret) {
+ size_t size = offsetof(EFI_FILE_SYSTEM_INFO, VolumeLabel) + 256U * sizeof(char16_t);
+ _cleanup_free_ EFI_FILE_SYSTEM_INFO *fsi = NULL;
+ EFI_STATUS err;
+
+ assert(handle);
+ assert(ret);
+
+ fsi = xmalloc(size);
+ err = handle->GetInfo(handle, MAKE_GUID_PTR(EFI_FILE_SYSTEM_INFO), &size, fsi);
+ if (err == EFI_BUFFER_TOO_SMALL) {
+ free(fsi);
+ fsi = xmalloc(size); /* GetInfo tells us the required size, let's use that now */
+ err = handle->GetInfo(handle, MAKE_GUID_PTR(EFI_FILE_SYSTEM_INFO), &size, fsi);
+ }
+ if (err != EFI_SUCCESS)
+ return err;
+
+ *ret = fsi->ReadOnly;
+ return EFI_SUCCESS;
+}
+
EFI_STATUS readdir(
EFI_FILE *handle,
EFI_FILE_INFO **buffer,
void sort_pointer_array(void **array, size_t n_members, compare_pointer_func_t compare);
EFI_STATUS get_file_info(EFI_FILE *handle, EFI_FILE_INFO **ret, size_t *ret_size);
+EFI_STATUS get_volume_ro(EFI_FILE *handle, bool *ret);
EFI_STATUS readdir(EFI_FILE *handle, EFI_FILE_INFO **buffer, size_t *buffer_size);
bool is_ascii(const char16_t *f);