From 82f6245d5bfd9b9e94c013f3c3b01e685adcb6aa Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 30 Sep 2016 15:41:12 +0000 Subject: [PATCH] Fix a cluster of bugs in list EFI environment variables: 1. Size returned for variable name is in bytes, not CHAR16 (the UEFI standard is unclear on this, where it is clear on the size of the variable). 2. Dynamically allocate the buffers so we can grow them if someone defines a super-long variable name. These two fixes allow me to examine all the variables in my BIOS and also removes the repeated printing of variables. --- sys/boot/efi/loader/main.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c index 9fed1f0ee100..18b0f3cfec27 100644 --- a/sys/boot/efi/loader/main.c +++ b/sys/boot/efi/loader/main.c @@ -814,8 +814,10 @@ command_efi_show(int argc, char *argv[]) EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} }; EFI_GUID matchguid = { 0,0,0,{0,0,0,0,0,0,0,0} }; uint32_t uuid_status; - CHAR16 varname[128]; + CHAR16 *varname; + CHAR16 *newnm; CHAR16 varnamearg[128]; + UINTN varalloc; UINTN varsz; while ((ch = getopt(argc, argv, "ag:lv:")) != -1) { @@ -910,10 +912,33 @@ command_efi_show(int argc, char *argv[]) * to specify the initial call must be a poiner to a NULL * character. */ - varsz = nitems(varname); + varalloc = 1024; + varname = malloc(varalloc); + if (varname == NULL) { + printf("Can't allocate memory to get variables\n"); + pager_close(); + return (CMD_ERROR); + } varname[0] = 0; - while ((status = RS->GetNextVariableName(&varsz, varname, &varguid)) != - EFI_NOT_FOUND) { + while (1) { + varsz = varalloc; + status = RS->GetNextVariableName(&varsz, varname, &varguid); + if (status == EFI_BUFFER_TOO_SMALL) { + varalloc = varsz; + newnm = malloc(varalloc); + if (newnm == NULL) { + printf("Can't allocate memory to get variables\n"); + free(varname); + pager_close(); + return (CMD_ERROR); + } + memcpy(newnm, varname, varsz); + free(varname); + varname = newnm; + continue; /* Try again with bigger buffer */ + } + if (status != EFI_SUCCESS) + break; if (aflag) { if (efi_print_var(varname, &varguid, lflag) != CMD_OK) break; @@ -934,6 +959,7 @@ command_efi_show(int argc, char *argv[]) } } } + free(varname); pager_close(); return (CMD_OK);