@@ -31,7 +31,11 @@ variables. All EFI variables use the vendor UUID
|
||||
* The EFI variable `LoaderConfigTimeout` contains the boot menu timeout
|
||||
currently in use. It may be modified both by the boot loader and by the
|
||||
host. The value should be formatted as numeric, NUL-terminated, decimal
|
||||
string, in UTF-16. The time is specified in µs.
|
||||
string, in UTF-16. The time is specified in seconds. A value of `menu-force`
|
||||
will disable the timeout and show the menu indefinitely. If set to `0` or
|
||||
`menu-hidden` the default entry is booted immediately without showing a menu.
|
||||
The boot loader should provide a way to interrupt this by for example
|
||||
listening for key presses for a brief moment before booting.
|
||||
|
||||
* Similarly, the EFI variable `LoaderConfigTimeoutOneShot` contains a boot menu
|
||||
timeout for a single following boot. It is set by the OS in order to request
|
||||
|
||||
@@ -257,12 +257,13 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><keycap>Esc</keycap></term>
|
||||
<term><keycombo><keycap>Ctrl</keycap><keycap>c</keycap></keycombo></term>
|
||||
<listitem><para>Abort the edit and quit the editor</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycombo><keycap>Ctrl</keycap><keycap>k</keycap></keycombo></term>
|
||||
<listitem><para>Clear the command line</para></listitem>
|
||||
<listitem><para>Clear the command line forwards</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -272,6 +273,7 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><keycombo><keycap>Ctrl</keycap><keycap>Del</keycap></keycombo></term>
|
||||
<term><keycombo><keycap>Alt</keycap><keycap>d</keycap></keycombo></term>
|
||||
<listitem><para>Delete word forwards</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+53
-21
@@ -254,6 +254,7 @@ static bool line_edit(
|
||||
cursor_left(&cursor, &first);
|
||||
continue;
|
||||
|
||||
case KEYPRESS(EFI_CONTROL_PRESSED, SCAN_DELETE, 0):
|
||||
case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'):
|
||||
/* kill-word */
|
||||
clear = 0;
|
||||
@@ -317,8 +318,8 @@ static bool line_edit(
|
||||
|
||||
case KEYPRESS(0, 0, CHAR_LINEFEED):
|
||||
case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
|
||||
case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */
|
||||
case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
|
||||
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
|
||||
case KEYPRESS(0, SCAN_F3, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
|
||||
if (!streq16(line, *line_in)) {
|
||||
free(*line_in);
|
||||
*line_in = TAKE_PTR(line);
|
||||
@@ -868,8 +869,8 @@ static bool menu_run(
|
||||
|
||||
case KEYPRESS(0, 0, CHAR_LINEFEED):
|
||||
case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
|
||||
case KEYPRESS(0, CHAR_CARRIAGE_RETURN, 0): /* EZpad Mini 4s firmware sends malformed events */
|
||||
case KEYPRESS(0, CHAR_CARRIAGE_RETURN, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
|
||||
case KEYPRESS(0, SCAN_F3, 0): /* EZpad Mini 4s firmware sends malformed events */
|
||||
case KEYPRESS(0, SCAN_F3, CHAR_CARRIAGE_RETURN): /* Teclast X98+ II firmware sends malformed events */
|
||||
case KEYPRESS(0, SCAN_RIGHT, 0):
|
||||
exit = true;
|
||||
break;
|
||||
@@ -1036,11 +1037,20 @@ static bool menu_run(
|
||||
}
|
||||
|
||||
if (timeout_efivar_saved != config->timeout_sec_efivar) {
|
||||
if (config->timeout_sec_efivar == TIMEOUT_UNSET)
|
||||
switch (config->timeout_sec_efivar) {
|
||||
case TIMEOUT_UNSET:
|
||||
efivar_set(LOADER_GUID, L"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
else
|
||||
break;
|
||||
case TIMEOUT_MENU_FORCE:
|
||||
efivar_set(LOADER_GUID, u"LoaderConfigTimeout", u"menu-force", EFI_VARIABLE_NON_VOLATILE);
|
||||
break;
|
||||
case TIMEOUT_MENU_HIDDEN:
|
||||
efivar_set(LOADER_GUID, u"LoaderConfigTimeout", u"menu-hidden", EFI_VARIABLE_NON_VOLATILE);
|
||||
break;
|
||||
default:
|
||||
efivar_set_uint_string(LOADER_GUID, L"LoaderConfigTimeout",
|
||||
config->timeout_sec_efivar, EFI_VARIABLE_NON_VOLATILE);
|
||||
}
|
||||
}
|
||||
|
||||
clear_screen(COLOR_NORMAL);
|
||||
@@ -1531,6 +1541,34 @@ static void config_entry_add_type1(
|
||||
TAKE_PTR(entry);
|
||||
}
|
||||
|
||||
static EFI_STATUS efivar_get_timeout(const char16_t *var, uint32_t *ret_value) {
|
||||
_cleanup_free_ char16_t *value = NULL;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(var);
|
||||
assert(ret_value);
|
||||
|
||||
err = efivar_get(LOADER_GUID, var, &value);
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
if (streq16(value, u"menu-force")) {
|
||||
*ret_value = TIMEOUT_MENU_FORCE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
if (streq16(value, u"menu-hidden")) {
|
||||
*ret_value = TIMEOUT_MENU_HIDDEN;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t timeout;
|
||||
if (!parse_number16(value, &timeout, NULL))
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
*ret_value = MIN(timeout, TIMEOUT_TYPE_MAX);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
_cleanup_free_ char *content = NULL;
|
||||
UINTN value;
|
||||
@@ -1556,20 +1594,20 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
if (err == EFI_SUCCESS)
|
||||
config_defaults_load_from_file(config, content);
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &value);
|
||||
if (err == EFI_SUCCESS) {
|
||||
config->timeout_sec_efivar = MIN(value, TIMEOUT_TYPE_MAX);
|
||||
err = efivar_get_timeout(u"LoaderConfigTimeout", &config->timeout_sec_efivar);
|
||||
if (err == EFI_SUCCESS)
|
||||
config->timeout_sec = config->timeout_sec_efivar;
|
||||
}
|
||||
else if (err != EFI_NOT_FOUND)
|
||||
log_error_stall(u"Error reading LoaderConfigTimeout EFI variable: %r", err);
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &value);
|
||||
err = efivar_get_timeout(u"LoaderConfigTimeoutOneShot", &config->timeout_sec);
|
||||
if (err == EFI_SUCCESS) {
|
||||
/* Unset variable now, after all it's "one shot". */
|
||||
(void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
|
||||
|
||||
config->timeout_sec = MIN(value, TIMEOUT_TYPE_MAX);
|
||||
config->force_menu = true; /* force the menu when this is set */
|
||||
}
|
||||
} else if (err != EFI_NOT_FOUND)
|
||||
log_error_stall(u"Error reading LoaderConfigTimeoutOneShot EFI variable: %r", err);
|
||||
|
||||
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value);
|
||||
if (err == EFI_SUCCESS)
|
||||
@@ -2416,14 +2454,8 @@ static void config_write_entries_to_variable(Config *config) {
|
||||
|
||||
p = buffer = xmalloc(sz);
|
||||
|
||||
for (UINTN i = 0; i < config->entry_count; i++) {
|
||||
UINTN l;
|
||||
|
||||
l = strsize16(config->entries[i]->id);
|
||||
memcpy(p, config->entries[i]->id, l);
|
||||
|
||||
p += l;
|
||||
}
|
||||
for (UINTN i = 0; i < config->entry_count; i++)
|
||||
p = mempcpy(p, config->entries[i]->id, strsize16(config->entries[i]->id));
|
||||
|
||||
assert(p == buffer + sz);
|
||||
|
||||
|
||||
@@ -132,14 +132,19 @@ EFI_STATUS console_key_read(uint64_t *key, uint64_t timeout_usec) {
|
||||
|
||||
if (FLAGS_SET(keydata.KeyState.KeyShiftState, EFI_SHIFT_STATE_VALID)) {
|
||||
/* Do not distinguish between left and right keys (set both flags). */
|
||||
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_PRESSED)
|
||||
shift |= EFI_SHIFT_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_CONTROL_PRESSED)
|
||||
shift |= EFI_CONTROL_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_ALT_PRESSED)
|
||||
shift |= EFI_ALT_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_LOGO_PRESSED)
|
||||
shift |= EFI_LOGO_PRESSED;
|
||||
|
||||
/* Shift is not supposed to be reported for keys that can be represented as uppercase
|
||||
* unicode chars (Shift+f is reported as F instead). Some firmware does it anyway, so
|
||||
* filter those out. */
|
||||
if ((keydata.KeyState.KeyShiftState & EFI_SHIFT_PRESSED) &&
|
||||
keydata.Key.UnicodeChar == 0)
|
||||
shift |= EFI_SHIFT_PRESSED;
|
||||
}
|
||||
|
||||
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
|
||||
|
||||
+5
-10
@@ -116,8 +116,7 @@ static EFI_STATUS pack_cpio_one(
|
||||
*cpio_buffer = a;
|
||||
a = (char *) *cpio_buffer + *cpio_buffer_size;
|
||||
|
||||
memcpy(a, "070701", 6); /* magic ID */
|
||||
a += 6;
|
||||
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 */
|
||||
@@ -139,16 +138,14 @@ static EFI_STATUS pack_cpio_one(
|
||||
a = write_cpio_word(a, target_dir_prefix_size + fname_size + 2); /* fname size */
|
||||
a = write_cpio_word(a, 0); /* "crc" */
|
||||
|
||||
memcpy(a, target_dir_prefix, target_dir_prefix_size);
|
||||
a += target_dir_prefix_size;
|
||||
a = mempcpy(a, target_dir_prefix, target_dir_prefix_size);
|
||||
*(a++) = '/';
|
||||
a = mangle_filename(a, fname);
|
||||
|
||||
/* Pad to next multiple of 4 */
|
||||
a = pad4(a, *cpio_buffer);
|
||||
|
||||
memcpy(a, contents, contents_size);
|
||||
a += contents_size;
|
||||
a = mempcpy(a, contents, contents_size);
|
||||
|
||||
/* Pad to next multiple of 4 */
|
||||
a = pad4(a, *cpio_buffer);
|
||||
@@ -198,8 +195,7 @@ static EFI_STATUS pack_cpio_dir(
|
||||
*cpio_buffer = a = xrealloc(*cpio_buffer, *cpio_buffer_size, *cpio_buffer_size + l);
|
||||
a = (char *) *cpio_buffer + *cpio_buffer_size;
|
||||
|
||||
memcpy(a, "070701", 6); /* magic ID */
|
||||
a += 6;
|
||||
a = mempcpy(a, "070701", 6); /* magic ID */
|
||||
|
||||
a = write_cpio_word(a, (*inode_counter)++); /* inode */
|
||||
a = write_cpio_word(a, access_mode | 0040000 /* = S_IFDIR */); /* mode */
|
||||
@@ -215,8 +211,7 @@ static EFI_STATUS pack_cpio_dir(
|
||||
a = write_cpio_word(a, path_size + 1); /* fname size */
|
||||
a = write_cpio_word(a, 0); /* "crc" */
|
||||
|
||||
memcpy(a, path, path_size + 1);
|
||||
a += path_size + 1;
|
||||
a = mempcpy(a, path, path_size + 1);
|
||||
|
||||
/* Pad to next multiple of 4 */
|
||||
a = pad4(a, *cpio_buffer);
|
||||
|
||||
+6
-7
@@ -25,15 +25,14 @@ EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, char16_t uuid[static 37]) {
|
||||
if (DevicePathSubType(dp) != MEDIA_HARDDRIVE_DP)
|
||||
continue;
|
||||
|
||||
HARDDRIVE_DEVICE_PATH *hd = (HARDDRIVE_DEVICE_PATH *) dp;
|
||||
if (hd->SignatureType != SIGNATURE_TYPE_GUID)
|
||||
/* The HD device path may be misaligned. */
|
||||
HARDDRIVE_DEVICE_PATH hd;
|
||||
memcpy(&hd, dp, MIN(sizeof(hd), (size_t) DevicePathNodeLength(dp)));
|
||||
|
||||
if (hd.SignatureType != SIGNATURE_TYPE_GUID)
|
||||
continue;
|
||||
|
||||
/* Use memcpy in case the device path node is misaligned. */
|
||||
EFI_GUID sig;
|
||||
memcpy(&sig, hd->Signature, sizeof(hd->Signature));
|
||||
|
||||
GuidToString(uuid, &sig);
|
||||
GuidToString(uuid, (EFI_GUID *) &hd.Signature);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,13 @@ bool parse_number16(const char16_t *s, uint64_t *ret_u, const char16_t **ret_tai
|
||||
# define memcmp __builtin_memcmp
|
||||
# define memcpy __builtin_memcpy
|
||||
# define memset __builtin_memset
|
||||
|
||||
static inline void *mempcpy(void * restrict dest, const void * restrict src, size_t n) {
|
||||
if (!dest || !src || n == 0)
|
||||
return dest;
|
||||
memcpy(dest, src, n);
|
||||
return (uint8_t *) dest + n;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The actual implementations of builtins with efi_ prefix so we can unit test them. */
|
||||
|
||||
+7
-16
@@ -69,8 +69,7 @@ static EFI_STATUS combine_initrd(
|
||||
|
||||
/* Order matters, the real initrd must come first, since it might include microcode updates
|
||||
* which the kernel only looks for in the first cpio archive */
|
||||
memcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
||||
p += initrd_size;
|
||||
p = mempcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size);
|
||||
|
||||
pad = ALIGN4(initrd_size) - initrd_size;
|
||||
if (pad > 0) {
|
||||
@@ -79,20 +78,12 @@ static EFI_STATUS combine_initrd(
|
||||
}
|
||||
}
|
||||
|
||||
if (credential_initrd) {
|
||||
memcpy(p, credential_initrd, credential_initrd_size);
|
||||
p += credential_initrd_size;
|
||||
}
|
||||
|
||||
if (global_credential_initrd) {
|
||||
memcpy(p, global_credential_initrd, global_credential_initrd_size);
|
||||
p += global_credential_initrd_size;
|
||||
}
|
||||
|
||||
if (sysext_initrd) {
|
||||
memcpy(p, sysext_initrd, sysext_initrd_size);
|
||||
p += sysext_initrd_size;
|
||||
}
|
||||
if (credential_initrd)
|
||||
p = mempcpy(p, credential_initrd, credential_initrd_size);
|
||||
if (global_credential_initrd)
|
||||
p = mempcpy(p, global_credential_initrd, global_credential_initrd_size);
|
||||
if (sysext_initrd)
|
||||
p = mempcpy(p, sysext_initrd, sysext_initrd_size);
|
||||
|
||||
assert((uint8_t*) PHYSICAL_ADDRESS_TO_POINTER(base) + n == p);
|
||||
|
||||
|
||||
+9
-12
@@ -751,21 +751,18 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
|
||||
end_node = NextDevicePathNode(end_node);
|
||||
|
||||
size_t file_size = strsize16(file);
|
||||
size_t dp_size = ((uint8_t *) end_node - (uint8_t *) dp) + END_DEVICE_PATH_LENGTH;
|
||||
size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp;
|
||||
|
||||
/* Make a copy that can also hold a file media device path. */
|
||||
*ret_dp = xmalloc(dp_size + file_size + SIZE_OF_FILEPATH_DEVICE_PATH);
|
||||
memcpy(*ret_dp, dp, dp_size);
|
||||
*ret_dp = xmalloc(dp_size + file_size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
|
||||
dp = mempcpy(*ret_dp, dp, dp_size);
|
||||
|
||||
/* Point dp to the end node of the copied device path. */
|
||||
dp = (EFI_DEVICE_PATH *) ((uint8_t *) *ret_dp + dp_size - END_DEVICE_PATH_LENGTH);
|
||||
|
||||
/* Replace end node with file media device path. */
|
||||
FILEPATH_DEVICE_PATH *file_dp = (FILEPATH_DEVICE_PATH *) dp;
|
||||
file_dp->Header.Type = MEDIA_DEVICE_PATH;
|
||||
file_dp->Header.SubType = MEDIA_FILEPATH_DP;
|
||||
memcpy(&file_dp->PathName, file, file_size);
|
||||
SetDevicePathNodeLength(&file_dp->Header, SIZE_OF_FILEPATH_DEVICE_PATH + file_size);
|
||||
/* Replace end node with file media device path. Use memcpy() in case dp is unaligned (if accessed as
|
||||
* FILEPATH_DEVICE_PATH). */
|
||||
dp->Type = MEDIA_DEVICE_PATH;
|
||||
dp->SubType = MEDIA_FILEPATH_DP;
|
||||
memcpy((uint8_t *) dp + offsetof(FILEPATH_DEVICE_PATH, PathName), file, file_size);
|
||||
SetDevicePathNodeLength(dp, offsetof(FILEPATH_DEVICE_PATH, PathName) + file_size);
|
||||
|
||||
dp = NextDevicePathNode(dp);
|
||||
SetDevicePathEndNode(dp);
|
||||
|
||||
+40
-41
@@ -12,33 +12,29 @@ union GptHeaderBuffer {
|
||||
uint8_t space[CONST_ALIGN_TO(sizeof(EFI_PARTITION_TABLE_HEADER), 512)];
|
||||
};
|
||||
|
||||
static EFI_DEVICE_PATH *path_chop(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) {
|
||||
static EFI_DEVICE_PATH *path_replace_hd(
|
||||
const EFI_DEVICE_PATH *path,
|
||||
const EFI_DEVICE_PATH *node,
|
||||
const HARDDRIVE_DEVICE_PATH *new_node) {
|
||||
|
||||
/* Create a new device path as a copy of path, while chopping off the remainder starting at the given
|
||||
* node. If new_node is provided, it is appended at the end of the new path. */
|
||||
|
||||
assert(path);
|
||||
assert(node);
|
||||
|
||||
UINTN len = (uint8_t *) node - (uint8_t *) path;
|
||||
EFI_DEVICE_PATH *chopped = xmalloc(len + END_DEVICE_PATH_LENGTH);
|
||||
size_t len = (uint8_t *) node - (uint8_t *) path, new_node_len = 0;
|
||||
if (new_node)
|
||||
new_node_len = DevicePathNodeLength(&new_node->Header);
|
||||
|
||||
memcpy(chopped, path, len);
|
||||
SetDevicePathEndNode((EFI_DEVICE_PATH *) ((uint8_t *) chopped + len));
|
||||
EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + END_DEVICE_PATH_LENGTH);
|
||||
EFI_DEVICE_PATH *end = mempcpy(ret, path, len);
|
||||
|
||||
return chopped;
|
||||
}
|
||||
if (new_node)
|
||||
end = mempcpy(end, new_node, new_node_len);
|
||||
|
||||
static EFI_DEVICE_PATH *path_dup(const EFI_DEVICE_PATH *dp) {
|
||||
assert(dp);
|
||||
|
||||
const EFI_DEVICE_PATH *node = dp;
|
||||
size_t size = 0;
|
||||
while (!IsDevicePathEnd(node)) {
|
||||
size += DevicePathNodeLength(node);
|
||||
node = NextDevicePathNode(node);
|
||||
}
|
||||
size += DevicePathNodeLength(node);
|
||||
|
||||
EFI_DEVICE_PATH *dup = xmalloc(size);
|
||||
memcpy(dup, dp, size);
|
||||
return dup;
|
||||
SetDevicePathEndNode(end);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_expected) {
|
||||
@@ -71,7 +67,7 @@ static bool verify_gpt(union GptHeaderBuffer *gpt_header_buffer, EFI_LBA lba_exp
|
||||
if (h->MyLBA != lba_expected)
|
||||
return false;
|
||||
|
||||
if (h->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))
|
||||
if ((h->SizeOfPartitionEntry % sizeof(EFI_PARTITION_ENTRY)) != 0)
|
||||
return false;
|
||||
|
||||
if (h->NumberOfPartitionEntries <= 0 || h->NumberOfPartitionEntries > 1024)
|
||||
@@ -134,28 +130,33 @@ static EFI_STATUS try_gpt(
|
||||
|
||||
/* Now we can finally look for xbootloader partitions. */
|
||||
for (UINTN i = 0; i < gpt.gpt_header.NumberOfPartitionEntries; i++) {
|
||||
EFI_PARTITION_ENTRY *entry;
|
||||
EFI_LBA start, end;
|
||||
|
||||
entry = (EFI_PARTITION_ENTRY*) ((uint8_t*) entries + gpt.gpt_header.SizeOfPartitionEntry * i);
|
||||
EFI_PARTITION_ENTRY *entry =
|
||||
(EFI_PARTITION_ENTRY *) ((uint8_t *) entries + gpt.gpt_header.SizeOfPartitionEntry * i);
|
||||
|
||||
if (memcmp(&entry->PartitionTypeGUID, XBOOTLDR_GUID, sizeof(entry->PartitionTypeGUID)) != 0)
|
||||
continue;
|
||||
|
||||
/* Let's use memcpy(), in case the structs are not aligned (they really should be though) */
|
||||
memcpy(&start, &entry->StartingLBA, sizeof(start));
|
||||
memcpy(&end, &entry->EndingLBA, sizeof(end));
|
||||
|
||||
if (end < start) /* Bogus? */
|
||||
if (entry->EndingLBA < entry->StartingLBA) /* Bogus? */
|
||||
continue;
|
||||
|
||||
ret_hd->PartitionNumber = i + 1;
|
||||
ret_hd->PartitionStart = start;
|
||||
ret_hd->PartitionSize = end - start + 1;
|
||||
ret_hd->MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
|
||||
ret_hd->SignatureType = SIGNATURE_TYPE_GUID;
|
||||
*ret_hd = (HARDDRIVE_DEVICE_PATH) {
|
||||
.Header = {
|
||||
.Type = MEDIA_DEVICE_PATH,
|
||||
.SubType = MEDIA_HARDDRIVE_DP,
|
||||
},
|
||||
.PartitionNumber = i + 1,
|
||||
.PartitionStart = entry->StartingLBA,
|
||||
.PartitionSize = entry->EndingLBA - entry->StartingLBA + 1,
|
||||
.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER,
|
||||
.SignatureType = SIGNATURE_TYPE_GUID,
|
||||
};
|
||||
memcpy(ret_hd->Signature, &entry->UniquePartitionGUID, sizeof(ret_hd->Signature));
|
||||
|
||||
/* HARDDRIVE_DEVICE_PATH has padding, which at least OVMF does not like. */
|
||||
SetDevicePathNodeLength(
|
||||
&ret_hd->Header,
|
||||
offsetof(HARDDRIVE_DEVICE_PATH, SignatureType) + sizeof(ret_hd->SignatureType));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -192,7 +193,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
|
||||
|
||||
/* Chop off the partition part, leaving us with the full path to the disk itself. */
|
||||
_cleanup_free_ EFI_DEVICE_PATH *disk_path = NULL;
|
||||
EFI_DEVICE_PATH *p = disk_path = path_chop(partition_path, part_node);
|
||||
EFI_DEVICE_PATH *p = disk_path = path_replace_hd(partition_path, part_node, NULL);
|
||||
|
||||
EFI_HANDLE disk_handle;
|
||||
EFI_BLOCK_IO_PROTOCOL *block_io;
|
||||
@@ -214,7 +215,6 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
|
||||
|
||||
/* Try several copies of the GPT header, in case one is corrupted */
|
||||
EFI_LBA backup_lba = 0;
|
||||
HARDDRIVE_DEVICE_PATH hd = *((HARDDRIVE_DEVICE_PATH *) part_node);
|
||||
for (UINTN nr = 0; nr < 3; nr++) {
|
||||
EFI_LBA lba;
|
||||
|
||||
@@ -230,6 +230,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
|
||||
else
|
||||
continue;
|
||||
|
||||
HARDDRIVE_DEVICE_PATH hd;
|
||||
err = try_gpt(
|
||||
block_io, lba,
|
||||
nr == 0 ? &backup_lba : NULL, /* Only get backup LBA location from first GPT header. */
|
||||
@@ -243,9 +244,7 @@ static EFI_STATUS find_device(EFI_HANDLE *device, EFI_DEVICE_PATH **ret_device_p
|
||||
}
|
||||
|
||||
/* Patch in the data we found */
|
||||
EFI_DEVICE_PATH *xboot_path = path_dup(partition_path);
|
||||
memcpy((uint8_t *) xboot_path + ((uint8_t *) part_node - (uint8_t *) partition_path), &hd, sizeof(hd));
|
||||
*ret_device_path = xboot_path;
|
||||
*ret_device_path = path_replace_hd(partition_path, part_node, &hd);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user