diff options
| author | Daniel Drake <drake@endlessm.com> | 2017-01-05 12:45:59 -0600 |
|---|---|---|
| committer | Daniel Drake <drake@endlessm.com> | 2017-01-05 12:45:59 -0600 |
| commit | fb08d687562b47899bd3333f40d25c3f92b479c3 (patch) | |
| tree | e1c48e75496eea7d865a59444cb9b97cd9eafe49 /fallback.c | |
| parent | a82f9bca38a0c9d10d09932622aee36e0283ea94 (diff) | |
| download | efi-boot-shim-fb08d687562b47899bd3333f40d25c3f92b479c3.tar.gz efi-boot-shim-fb08d687562b47899bd3333f40d25c3f92b479c3.zip | |
fallback: replace any existing boot entry with the same name
Tweak the dupliate boot entry detection code to consider any existing
entries as duplicate if they have the same name (rather than requiring
the existing entry to be completely identical to the one we would add).
When a duplicate is detected, rewrite the whole variable (as the device
details might have changed) in addition to making it the new default
boot entry.
This means that when partition UUIDs are changed, or when doing a fresh
reflash, we will avoid creating duplicate entries with the same name.
https://phabricator.endlessm.com/T14430
Diffstat (limited to 'fallback.c')
| -rw-r--r-- | fallback.c | 225 |
1 files changed, 101 insertions, 124 deletions
@@ -143,125 +143,116 @@ VOID *first_new_option_args = NULL; UINTN first_new_option_size = 0; EFI_STATUS -add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, - CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) +do_add_boot_option(int boot_entry_num, EFI_DEVICE_PATH *hddp, + EFI_DEVICE_PATH *fulldp, CHAR16 *filename, CHAR16 *label, + CHAR16 *arguments) { - static int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; EFI_GUID global = EFI_GLOBAL_VARIABLE; EFI_STATUS rc; - for(; i <= 0xffff; i++) { - varname[4] = hexmap[(i & 0xf000) >> 12]; - varname[5] = hexmap[(i & 0x0f00) >> 8]; - varname[6] = hexmap[(i & 0x00f0) >> 4]; - varname[7] = hexmap[(i & 0x000f) >> 0]; + varname[4] = hexmap[(boot_entry_num & 0xf000) >> 12]; + varname[5] = hexmap[(boot_entry_num & 0x0f00) >> 8]; + varname[6] = hexmap[(boot_entry_num & 0x00f0) >> 4]; + varname[7] = hexmap[(boot_entry_num & 0x000f) >> 0]; - void *var = LibGetVariable(varname, &global); - if (!var) { - int size = sizeof(UINT32) + sizeof (UINT16) + - StrLen(label)*2 + 2 + DevicePathSize(hddp) + - StrLen(arguments) * 2; - - CHAR8 *data = AllocateZeroPool(size + 2); - CHAR8 *cursor = data; - *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; - cursor += sizeof (UINT32); - *(UINT16 *)cursor = DevicePathSize(hddp); - cursor += sizeof (UINT16); - StrCpy((CHAR16 *)cursor, label); - cursor += StrLen(label)*2 + 2; - CopyMem(cursor, hddp, DevicePathSize(hddp)); - cursor += DevicePathSize(hddp); - StrCpy((CHAR16 *)cursor, arguments); + int size = sizeof(UINT32) + sizeof (UINT16) + + StrLen(label)*2 + 2 + DevicePathSize(hddp) + + StrLen(arguments) * 2; + + CHAR8 *data = AllocateZeroPool(size + 2); + CHAR8 *cursor = data; + *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; + cursor += sizeof (UINT32); + *(UINT16 *)cursor = DevicePathSize(hddp); + cursor += sizeof (UINT16); + StrCpy((CHAR16 *)cursor, label); + cursor += StrLen(label)*2 + 2; + CopyMem(cursor, hddp, DevicePathSize(hddp)); + cursor += DevicePathSize(hddp); + StrCpy((CHAR16 *)cursor, arguments); #ifdef DEBUG_FALLBACK - Print(L"Creating boot entry \"%s\" with label \"%s\" " - L"for file \"%s\"\n", - varname, label, filename); + Print(L"Creating boot entry \"%s\" with label \"%s\" " + L"for file \"%s\"\n", + varname, label, filename); #endif - if (!first_new_option) { - first_new_option = DuplicateDevicePath(fulldp); - first_new_option_args = arguments; - first_new_option_size = StrLen(arguments) * sizeof (CHAR16); - } + if (!first_new_option) { + first_new_option = DuplicateDevicePath(fulldp); + first_new_option_args = arguments; + first_new_option_size = StrLen(arguments) * sizeof (CHAR16); + } - rc = uefi_call_wrapper(RT->SetVariable, 5, varname, - &global, EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - size, data); + rc = uefi_call_wrapper(RT->SetVariable, 5, varname, + &global, EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, data); - FreePool(data); + FreePool(data); - if (EFI_ERROR(rc)) { - Print(L"Could not create variable: %d\n", rc); - return rc; - } + if (EFI_ERROR(rc)) { + Print(L"Could not create variable: %d\n", rc); + return rc; + } - CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16) - * (nbootorder + 1)); - if (!newbootorder) - return EFI_OUT_OF_RESOURCES; + CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16) + * (nbootorder + 1)); + if (!newbootorder) + return EFI_OUT_OF_RESOURCES; - int j = 0; - newbootorder[0] = i & 0xffff; - if (nbootorder) { - for (j = 0; j < nbootorder; j++) - newbootorder[j+1] = bootorder[j]; - FreePool(bootorder); - } - bootorder = newbootorder; - nbootorder += 1; + int j = 0; + newbootorder[0] = boot_entry_num & 0xffff; + if (nbootorder) { + for (j = 0; j < nbootorder; j++) + newbootorder[j+1] = bootorder[j]; + FreePool(bootorder); + } + bootorder = newbootorder; + nbootorder += 1; #ifdef DEBUG_FALLBACK - Print(L"nbootorder: %d\nBootOrder: ", nbootorder); - for (j = 0 ; j < nbootorder ; j++) - Print(L"%04x ", bootorder[j]); - Print(L"\n"); + Print(L"nbootorder: %d\nBootOrder: ", nbootorder); + for (j = 0 ; j < nbootorder ; j++) + Print(L"%04x ", bootorder[j]); + Print(L"\n"); #endif - return EFI_SUCCESS; - } - } - return EFI_OUT_OF_RESOURCES; + return EFI_SUCCESS; } EFI_STATUS -find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, - CHAR16 *filename, CHAR16 *label, CHAR16 *arguments, - UINT16 *optnum) +add_new_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, + CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) { - unsigned int size = sizeof(UINT32) + sizeof (UINT16) + - StrLen(label)*2 + 2 + DevicePathSize(dp) + - StrLen(arguments) * 2; + static int i = 0; + CHAR16 varname[] = L"Boot0000"; + CHAR16 hexmap[] = L"0123456789ABCDEF"; + EFI_GUID global = EFI_GLOBAL_VARIABLE; - CHAR8 *data = AllocateZeroPool(size + 2); - if (!data) - return EFI_OUT_OF_RESOURCES; - CHAR8 *cursor = data; - *(UINT32 *)cursor = LOAD_OPTION_ACTIVE; - cursor += sizeof (UINT32); - *(UINT16 *)cursor = DevicePathSize(dp); - cursor += sizeof (UINT16); - StrCpy((CHAR16 *)cursor, label); - cursor += StrLen(label)*2 + 2; - CopyMem(cursor, dp, DevicePathSize(dp)); - cursor += DevicePathSize(dp); - StrCpy((CHAR16 *)cursor, arguments); + for(; i <= 0xffff; i++) { + varname[4] = hexmap[(i & 0xf000) >> 12]; + varname[5] = hexmap[(i & 0x0f00) >> 8]; + varname[6] = hexmap[(i & 0x00f0) >> 4]; + varname[7] = hexmap[(i & 0x000f) >> 0]; + + void *var = LibGetVariable(varname, &global); + if (!var) + return do_add_boot_option(i, hddp, fulldp, filename, + label, arguments); + } + return EFI_OUT_OF_RESOURCES; +} +int +find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, + CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) +{ int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; EFI_GUID global = EFI_GLOBAL_VARIABLE; - EFI_STATUS rc; - - CHAR8 *candidate = AllocateZeroPool(size); - if (!candidate) { - FreePool(data); - return EFI_OUT_OF_RESOURCES; - } for(i = 0; i < nbootorder && i < 0x10000; i++) { varname[4] = hexmap[(bootorder[i] & 0xf000) >> 12]; @@ -269,33 +260,29 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, varname[6] = hexmap[(bootorder[i] & 0x00f0) >> 4]; varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0]; - UINTN candidate_size = size; - rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global, - NULL, &candidate_size, candidate); - if (EFI_ERROR(rc)) + UINTN candidate_size; + CHAR8 *candidate = LibGetVariableAndSize(varname, &global, + &candidate_size); + if (!candidate) continue; - if (candidate_size != size) + /* Check that we won't overrun the buffer when comparing */ + if (candidate_size < (StrLen(label) * 2) + 2 + 6) { + FreePool(candidate); continue; + } - if (CompareMem(candidate, data, size)) + /* Check if this entry has the same label */ + if (CompareMem(candidate + 6, label, StrLen(label) * 2 + 2)) { + FreePool(candidate); continue; - - /* at this point, we have duplicate data. */ - if (!first_new_option) { - first_new_option = DuplicateDevicePath(fulldp); - first_new_option_args = arguments; - first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } - *optnum = i; + /* at this point, we have duplicate data. */ FreePool(candidate); - FreePool(data); - return EFI_SUCCESS; + return i; } - FreePool(candidate); - FreePool(data); - return EFI_NOT_FOUND; + return -1; } EFI_STATUS @@ -412,22 +399,12 @@ add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 * } #endif - UINT16 option; - rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option); - if (EFI_ERROR(rc)) { - add_boot_option(dp, full_device_path, fullpath, label, arguments); - } else if (option != 0) { - CHAR16 *newbootorder; - newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder); - if (!newbootorder) - return EFI_OUT_OF_RESOURCES; - - newbootorder[0] = bootorder[option]; - CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option); - CopyMem(newbootorder + option + 1, bootorder + option + 1, - sizeof (CHAR16) * (nbootorder - option - 1)); - FreePool(bootorder); - bootorder = newbootorder; + int boot_entry_num = find_boot_option(dp, full_device_path, fullpath, + label, arguments); + if (boot_entry_num < 0) { + add_new_boot_option(dp, full_device_path, fullpath, label, arguments); + } else { + do_add_boot_option(boot_entry_num, dp, full_device_path, fullpath, label, arguments); } err: |
