diff options
| -rw-r--r-- | shim.c | 96 |
1 files changed, 50 insertions, 46 deletions
@@ -1411,6 +1411,10 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) return efi_status; } + /* Sanity check since we make several assumptions about the length */ + if (li->LoadOptionsSize % 2 != 0) + return EFI_INVALID_PARAMETER; + /* So, load options are a giant pain in the ass. If we're invoked * from the EFI shell, we get something like this: @@ -1504,6 +1508,26 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) */ UINTN strings = count_ucs2_strings(li->LoadOptions, li->LoadOptionsSize); + + /* + * In the case where strings == 1 check to see if L' ' is being used as + * a delimiter, if so replace it with NULLs since the code already + * handles that case. + */ + if (strings == 1) { + UINT16 *cur = li->LoadOptions; + + /* replace L' ' with L'\0' if we find any */ + for (i = 0; i < li->LoadOptionsSize / 2; i++) { + if (cur[i] == L' ') + cur[i] = L'\0'; + } + + /* redo the string count */ + strings = count_ucs2_strings(li->LoadOptions, + li->LoadOptionsSize); + } + /* * If it's not string data, try it as an EFI_LOAD_OPTION. */ @@ -1516,77 +1540,57 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) li->LoadOptionsSize, (UINT8 **)&start, &loader_len); - if (EFI_ERROR(efi_status)) - return EFI_SUCCESS; + if (EFI_ERROR(efi_status)) { + /* maybe this is just a single string? */ + start = li->LoadOptions; + loader_len = li->LoadOptionsSize; + } remaining_size = 0; } else if (strings >= 2) { /* * UEFI shell copies the whole line of the command into - * LoadOptions. We ignore the string before the first L' ', + * LoadOptions. We ignore the string before the first L'\0', * i.e. the name of this program. - * Counting by two bytes is safe, because we know the size is - * compatible with a UCS2-LE string. */ - UINT8 *cur = li->LoadOptions; - for (i = 0; i < li->LoadOptionsSize - 2; i += 2) { - CHAR16 c = (cur[i+1] << 8) | cur[i]; - if (c == L' ') { - start = (CHAR16 *)&cur[i+2]; - remaining_size = li->LoadOptionsSize - i - 2; + UINT16 *cur = li->LoadOptions; + for (i = 1; i < li->LoadOptionsSize / 2; i++) { + if (cur[i - 1] == L'\0') { + start = &cur[i]; + remaining_size = li->LoadOptionsSize - (i * 2); break; } } - - if (!start || remaining_size <= 0 || start[0] == L'\0') + /* if we didn't find at least one NULL, something is wrong */ + if (start == li->LoadOptions) return EFI_SUCCESS; - for (i = 0; start[i] != '\0'; i++) { - if (start[i] == L' ') - start[i] = L'\0'; - if (start[i] == L'\0') { - loader_len = 2 * i + 2; - break; - } - } - if (loader_len) - remaining_size -= loader_len; - } else { - /* only find one string */ - start = li->LoadOptions; - loader_len = li->LoadOptionsSize; - } - - /* - * Just to be sure all that math is right... - */ - if (loader_len % 2 != 0) - return EFI_INVALID_PARAMETER; - - strings = count_ucs2_strings((UINT8 *)start, loader_len); - if (strings < 1) - return EFI_SUCCESS; + while (start[loader_len++] != L'\0'); + loader_len *= 2; - /* - * And then I found a version of BDS that gives us our own path in - * LoadOptions: + remaining_size -= loader_len; + } else if (strings == 1 && is_our_path(li, start)) { + /* + * And then I found a version of BDS that gives us our own path + * in LoadOptions: 77162C58 5c 00 45 00 46 00 49 00 |\.E.F.I.| 77162C60 5c 00 42 00 4f 00 4f 00 54 00 5c 00 42 00 4f 00 |\.B.O.O.T.\.B.O.| 77162C70 4f 00 54 00 58 00 36 00 34 00 2e 00 45 00 46 00 |O.T.X.6.4...E.F.| 77162C80 49 00 00 00 |I...| - * which is just cruel... So yeah, just don't use it. - */ - if (strings == 1 && is_our_path(li, start)) + * which is just cruel... So yeah, just don't use it. + */ return EFI_SUCCESS; + } /* * Set up the name of the alternative loader and the LoadOptions for * the loader */ if (loader_len > 0) { - loader_str = AllocatePool(loader_len); + /* we might not always have a NULL at the end */ + loader_str = AllocatePool(loader_len + 2); if (!loader_str) { perror(L"Failed to allocate loader string\n"); return EFI_OUT_OF_RESOURCES; @@ -1594,7 +1598,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) for (i = 0; i < loader_len / 2; i++) loader_str[i] = start[i]; - loader_str[loader_len/2-1] = L'\0'; + loader_str[loader_len/2] = L'\0'; second_stage = loader_str; load_options = remaining_size ? start + (loader_len/2) : NULL; |
