From cf884399031c711205f837a5b65eeeb26fee3258 Mon Sep 17 00:00:00 2001 From: Konstantin Aladyshev Date: Fri, 25 Feb 2022 15:39:26 +0300 Subject: Add lesson 61 Signed-off-by: Konstantin Aladyshev --- Lessons/Lesson_61/README.md | 420 +++++++++++++++++++++ .../Lesson_61/UefiLessonsPkg/UefiLessonsPkg.dsc | 84 +++++ .../UpdateDmpstoreDump/UpdateDmpstoreDump.c | 123 ++++++ .../UpdateDmpstoreDump/UpdateDmpstoreDump.inf | 26 ++ Lessons/Lesson_61/bootorder.png | Bin 0 -> 10651 bytes Lessons/Lesson_61/hexedit_1.png | Bin 0 -> 5291 bytes Lessons/Lesson_61/hexedit_2.png | Bin 0 -> 5255 bytes Lessons/Lesson_61/hexedit_3.png | Bin 0 -> 5270 bytes Lessons/Lesson_61/hexedit_help.png | Bin 0 -> 6684 bytes 9 files changed, 653 insertions(+) create mode 100644 Lessons/Lesson_61/README.md create mode 100644 Lessons/Lesson_61/UefiLessonsPkg/UefiLessonsPkg.dsc create mode 100644 Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.c create mode 100644 Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf create mode 100644 Lessons/Lesson_61/bootorder.png create mode 100644 Lessons/Lesson_61/hexedit_1.png create mode 100644 Lessons/Lesson_61/hexedit_2.png create mode 100644 Lessons/Lesson_61/hexedit_3.png create mode 100644 Lessons/Lesson_61/hexedit_help.png (limited to 'Lessons') diff --git a/Lessons/Lesson_61/README.md b/Lessons/Lesson_61/README.md new file mode 100644 index 0000000..f0ef50b --- /dev/null +++ b/Lessons/Lesson_61/README.md @@ -0,0 +1,420 @@ +UEFI shell has a `dmpstore` command that helps to see content of UEFI variables. + +If you'll look at the help of the `dmpstore` command you could see one more useful feature that this command presents. With this command it is possible to save UEFI variables to a file and load them back from such files: +``` +FS0:\> dmpstore -? +... +DMPSTORE [-all | ([variable] [-guid guid])] [-s file] +DMPSTORE [-all | ([variable] [-guid guid])] [-l file] +... + -s - Saves variables to a file. + -l - Loads and sets variables from a file. +... +``` +Let's try to use this mechanics to modify content of an existing UEFI variable. It can be a useful feature for the debug. + +In some earlier lesson we've created the `ShowBootVariables.efi` application that displays boot sources based on the content of UEFU boot variables: +``` +FS0:\> ShowBootVariables.efi +Boot0000 +UiApp +Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331) + +Boot0001 +UEFI QEMU DVD-ROM QM00003 +PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) + +Boot0002* +EFI Internal Shell +Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1) + +Boot0003 +UEFI QEMU HARDDISK QM00001 +PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) +``` + +One of the variables that were parsed in this application is a `BootOrder` variable. Just in case you forgot: +``` +The BootOrder variable contains an array of UINT16’s that make up an ordered list of the Boot#### +options. The first element in the array is the value for the first logical boot option, the second element is +the value for the second logical boot option, etc. The BootOrder order list is used by the firmware’s +boot manager as the default boot order. +``` + +Print the content of the BootOrder variable +``` +FS0:\> dmpstore BootOrder +Variable NV+RT+BS 'EFIGlobalVariable:BootOrder' DataSize = 0x08 + 00000000: 00 00 01 00 02 00 03 00- *........* +``` +This means that the order is: +``` +Boot0000 +Boot0001 +Boot0002 +Boot0003 +``` +Everything is like our `ShowBootVariables` application shows. + +With a help of the `dmpstore` command we can dump the content of a `BootOrder` variable to a file: +``` +FS0:\> dmpstore BootOrder -s BootOrder.bin +Save variable to file: BootOrder.bin. +Variable NV+RT+BS '8BE4DF61-93CA-11D2-AA0D-00E098032B8C:BootOrder' DataSize = 0x08 +``` + +UEFI shell contains `hexedit` command in itself. With it we can see the content of a created file: + +![hexediti_1.png](hexedit_1.png?raw=true "BootOrder.bin before modifications") + +`hexedit` is a hex editor, you can see its help message with a `Ctrl+E` command: + +![hexedit_help.png](hexedit_help.png?raw=true "hexedit help") + +Exit help with `Ctrl-W`. + +`dmpstore` command represents each variable with a following structure in a file: +``` +{ + UINT32 NameSize; // Size of the variable name in bytes + UINT32 DataSize; // Size of the variable data in bytes + CHAR16 Name[NameSize/2]; // Variable name in CHAR16 + EFI_GUID Guid; // Variable GUID + UINT32 Attributes; // Variable attributes + UINT8 Data[DataSize]; // Variable data + UINT32 Crc; // CRC32 checksum for the record +} +``` + +Here is a file content with a highlight for the structure fileds: + +![bootorder.png](bootorder.png?raw=true "bootorder") + +Let's try to modify the file content changing the boot order to: +``` +Boot0001 +Boot0000 +Boot0002 +Boot0003 +``` + +![hexedit_2.png](hexedit_2.png?raw=true "hexedit after modification") + +Type `Ctrl+Q` to quit and enter `y` to save our modifications. + +If you'll try to load the changed settings you would get an error: +``` +FS0:\> dmpstore -l BootOrder.bin +Load and set variables from file: BootOrder.bin. +dmpstore: Incorrect file format. +dmpstore: No matching variables found. Guid 8BE4DF61-93CA-11D2-AA0D-00E098032B8C +``` +This is happening because `UINT32 Crc` field of the record is not longer valid for the current record content. + +Let's create an application `UpdateDmpstoreDump` to update CRC fields in the `dmpstore` dumps. + +Once again as we would parse command shell arguments it is better to create a shell application. We would read and write files, therefore include `ShellLib` to the `LibraryClasses`: +`UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf`: +``` +[Defines] + INF_VERSION = 1.25 + BASE_NAME = UpdateDmpstoreDump + FILE_GUID = d14fe21b-7dbf-40ff-96cb-5d6f5b63cda6 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + UpdateDmpstoreDump.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + ShellCEntryLib + ShellLib +``` + +In the `UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.c` we start from reading dump file name from the command argument and opening the file with read and write attributes: +``` +#include +#include +#include +#include + +VOID Usage() +{ + Print(L"Recalculate CRCs for dmpstore command dump\n"); + Print(L"\n"); + Print(L" UpdateDmpstoreDump \n"); +} + +INTN EFIAPI ShellAppMain(IN UINTN Argc, IN CHAR16 **Argv) +{ + if (Argc!=2) { + Usage(); + return EFI_INVALID_PARAMETER; + } + + SHELL_FILE_HANDLE FileHandle; + + CHAR16* Filename = Argv[1]; + EFI_STATUS Status = ShellOpenFileByName( + Filename, + &FileHandle, + EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't open file %s\n", Filename); + return Status; + } + + ... + + Status = ShellCloseFile(&FileHandle); + if (EFI_ERROR(Status)) { + Print(L"Can't close file: %r\n", Status); + } + + return EFI_SUCCESS; +} +``` + +The dump file can have many records in itself and the size of a record is not a constant, but depends on the record fields. Therefore the only way to fix all record CRCs is to step throught the file records until the file end: +``` + UINT64 FileSize; + Status = ShellGetFileSize(FileHandle, &FileSize); + if (EFI_ERROR(Status)) { + Status = ShellCloseFile(&FileHandle); + return SHELL_DEVICE_ERROR; + } + + UINT64 FilePos = 0; + while (FilePos < FileSize) { + ... + } +``` + +Here is a code to read record data and calculate its CRC32. It is pretty similar to the one that `dmpstore` command has it its `LoadVariablesFromFilefunction` (https://github.com/tianocore/edk2/blob/master/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c): +``` +UINTN ToReadSize; +UINT32 NameSize; +ToReadSize = sizeof(NameSize); +Status = ShellReadFile(FileHandle, &ToReadSize, &NameSize); +if (EFI_ERROR(Status) || (ToReadSize != sizeof(NameSize))) { + Status = SHELL_VOLUME_CORRUPTED; + break; +} +FilePos += ToReadSize; + +UINT32 DataSize; +ToReadSize = sizeof(DataSize); +Status = ShellReadFile(FileHandle, &ToReadSize, &DataSize); +if (EFI_ERROR(Status) || (ToReadSize != sizeof(DataSize))) { + Status = SHELL_VOLUME_CORRUPTED; + break; +} +FilePos += ToReadSize; + +UINTN RemainingSize = NameSize + + sizeof(EFI_GUID) + + sizeof(UINT32) + + DataSize; +UINT8* Buffer = AllocatePool(sizeof(NameSize) + sizeof(DataSize) + RemainingSize); +if (Buffer == NULL) { + Status = SHELL_OUT_OF_RESOURCES; + break; +} + +*(UINT32*)Buffer = NameSize; +*((UINT32*)Buffer + 1) = DataSize; + +ToReadSize = RemainingSize; +Status = ShellReadFile(FileHandle, &ToReadSize, (UINT32*)Buffer + 2); +if (EFI_ERROR(Status) || (ToReadSize != RemainingSize)) { + Status = SHELL_VOLUME_CORRUPTED; + FreePool (Buffer); + break; +} +FilePos += ToReadSize; + + +UINT32 Crc32; +gBS->CalculateCrc32 ( + Buffer, + sizeof(NameSize) + sizeof(DataSize) + RemainingSize, + &Crc32 +); + +... + +FreePool(Buffer); +``` + +To calculate the CRC32 checksum here we use `EFI_BOOT_SERVICES.CalculateCrc32()` function: +``` +EFI_BOOT_SERVICES.CalculateCrc32() + +Summary: +Computes and returns a 32-bit CRC for a data buffer. + +Prototype: +typedef +EFI_STATUS +(EFIAPI *EFI_CALCULATE_CRC32) + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *Crc32 + ); + +Parameters: +Data A pointer to the buffer on which the 32-bit CRC is to be computed. +DataSize The number of bytes in the buffer Data. +Crc32 The 32-bit CRC that was computed for the data buffer specified by Data and DataSize. + +Description: +This function computes the 32-bit CRC for the data buffer specified by Data and DataSize. If the 32-bit CRC is computed, then it is returned in Crc32 and EFI_SUCCESS is returned. +``` + +When we have our CRC32 checksum we can update file content with a help of a `ShellWriteFile` function: +``` +UINTN ToWriteSize = sizeof(Crc32); +Status = ShellWriteFile( + FileHandle, + &ToWriteSize, + &Crc32 +); +if (EFI_ERROR(Status) || (ToWriteSize != sizeof(Crc32))) { + Print(L"Error! Not all data was written\n"); + FreePool(Buffer); + break; +} +FilePos += ToWriteSize; +``` + +Build our application and use it on the `dmpstore` dump: +``` +FS0:\> UpdateDmpstoreDump.efi BootOrder.bin +``` + +If you look at the file content again you would see that the CRC field has changed. + +![hexedit_3.png](hexedit_3.png?raw=true "hexedit after CRC modification") + +Now `dmpstore -l` would finish without errors: +``` +FS0:\> dmpstore -l BootOrder.bin +Load and set variables from file: BootOrder.bin. +Variable NV+RT+BS '8BE4DF61-93CA-11D2-AA0D-00E098032B8C:BootOrder' DataSize = 0x08 +``` + +You can see that variable content was modified: +``` +FS0:\> dmpstore BootOrder +Variable NV+RT+BS 'EFIGlobalVariable:BootOrder' DataSize = 0x08 + 00000000: 01 00 00 00 02 00 03 00- *........* +``` + +You can also use our `ShowBootVariables.efi` application to see the changes: +``` +FS0:\> ShowBootVariables.efi +Boot0001 +UEFI QEMU DVD-ROM QM00003 +PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) + +Boot0000 +UiApp +Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(462CAA21-7614-4503-836E-8AB6F4662331) + +Boot0002* +EFI Internal Shell +Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/FvFile(7C04A583-9E3E-4F1C-AD65-E05268D0B4D1) + +Boot0003 +UEFI QEMU HARDDISK QM00001 +PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) +``` +__________________________ + +We can also verify that our program works in case when there are multiple variables in the dump file. + +Just in case you have some persistent variables from the previous lesson delete all the variables under our GUID with a `dmpstore -d -guid ` command: +``` +FS0:\> dmpstore -d -guid bb2a829f-7943-4691-a03a-f1f48519d7e6 +dmpstore: No matching variables found. Guid 7C04A583-9E3E-4F1C-AD65-E05268D0B4D1 + +``` + +Create new variables and save them to a file: +``` +FS0:\> SetVariableExample.efi HelloVar nb "Hello World" +Variable HelloVar was successfully changed +FS0:\> SetVariableExample.efi ByeVar nbr "Bye World" +Variable ByeVar was successfully changed +FS0:\> dmpstore -guid bb2a829f-7943-4691-a03a-f1f48519d7e6 -s MyVar.bin +Save variable to file: MyVar.bin. +Variable NV+RT+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:ByeVar' DataSize = 0x16 +Variable NV+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:HelloVar' DataSize = 0x1A +``` + +Use hexedit to modify `World` string in both records of a dump file. Here I've just increased each letter code with 1. + +Before: +``` +00000000 0E 00 00 00 14 00 00 00 42 00 79 00 65 00 56 00 ........B.y.e.V. +00000010 61 00 72 00 00 00 9F 82 2A BB 43 79 91 46 A0 3A a.r...??*?Cy?F?: +00000020 F1 F4 85 19 D7 E6 07 00 00 00 42 00 79 00 65 00 ???.??....B.y.e. +00000030 20 00 57 00 6F 00 72 00 6C 00 64 00 00 00 EC 24 .W.o.r.l.d...?$ +00000040 78 CD 12 00 00 00 18 00 00 00 48 00 65 00 6C 00 x?........H.e.l. +00000050 6C 00 6F 00 56 00 61 00 72 00 00 00 9F 82 2A BB l.o.V.a.r...??*? +00000060 43 79 91 46 A0 3A F1 F4 85 19 D7 E6 03 00 00 00 Cy?F?:???.??.... +00000070 48 00 65 00 6C 00 6C 00 6F 00 20 00 57 00 6F 00 H.e.l.l.o. .W.o. +00000080 72 00 6C 00 64 00 00 00 97 82 10 13 r.l.d...??.. +``` +After: +``` +00000000 0E 00 00 00 14 00 00 00 42 00 79 00 65 00 56 00 ........B.y.e.V. +00000010 61 00 72 00 00 00 9F 82 2A BB 43 79 91 46 A0 3A a.r...??*?Cy?F?: +00000020 F1 F4 85 19 D7 E6 07 00 00 00 42 00 79 00 65 00 ???.??....B.y.e. +00000030 20 00 58 00 70 00 73 00 6D 00 65 00 00 00 EC 24 .X.p.s.m.e...?$ +00000040 78 CD 12 00 00 00 18 00 00 00 48 00 65 00 6C 00 x?........H.e.l. +00000050 6C 00 6F 00 56 00 61 00 72 00 00 00 9F 82 2A BB l.o.V.a.r...??*? +00000060 43 79 91 46 A0 3A F1 F4 85 19 D7 E6 03 00 00 00 Cy?F?:???.??.... +00000070 48 00 65 00 6C 00 6C 00 6F 00 20 00 58 00 70 00 H.e.l.l.o. .X.p. +00000080 73 00 6D 00 65 00 00 00 97 82 10 13 s.m.e...??.. +``` + +Use our program to update checksums: +``` +FS0:\> UpdateDmpstoreDump.efi MyVar.bin +``` + +Now you can verify that our new dump indeed have changed both variables content: +``` +FS0:\> dmpstore -guid bb2a829f-7943-4691-a03a-f1f48519d7e6 +Variable NV+RT+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:ByeVar' DataSize = 0x14 + 00000000: 42 00 79 00 65 00 20 00-57 00 6F 00 72 00 6C 00 *B.y.e. .W.o.r.l.* + 00000010: 64 00 00 00 *d...* +Variable NV+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:HelloVar' DataSize = 0x18 + 00000000: 48 00 65 00 6C 00 6C 00-6F 00 20 00 57 00 6F 00 *H.e.l.l.o. .W.o.* + 00000010: 72 00 6C 00 64 00 00 00- *r.l.d...* + +FS0:\> dmpstore -guid bb2a829f-7943-4691-a03a-f1f48519d7e6 -l MyVar.bin +Load and set variables from file: MyVar.bin. +Variable NV+RT+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:ByeVar' DataSize = 0x14 +Variable NV+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:HelloVar' DataSize = 0x18 + +FS0:\> dmpstore -guid bb2a829f-7943-4691-a03a-f1f48519d7e6 +Variable NV+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:HelloVar' DataSize = 0x18 + 00000000: 48 00 65 00 6C 00 6C 00-6F 00 20 00 58 00 70 00 *H.e.l.l.o. .X.p.* + 00000010: 73 00 6D 00 65 00 00 00- *s.m.e...* +Variable NV+RT+BS 'BB2A829F-7943-4691-A03A-F1F48519D7E6:ByeVar' DataSize = 0x14 + 00000000: 42 00 79 00 65 00 20 00-58 00 70 00 73 00 6D 00 *B.y.e. .X.p.s.m.* + 00000010: 65 00 00 00 *e...* +``` + +Keep in mind that if you change size of the variable data, you need to change the `UINT32 DataSize` field as well. diff --git a/Lessons/Lesson_61/UefiLessonsPkg/UefiLessonsPkg.dsc b/Lessons/Lesson_61/UefiLessonsPkg/UefiLessonsPkg.dsc new file mode 100644 index 0000000..2180620 --- /dev/null +++ b/Lessons/Lesson_61/UefiLessonsPkg/UefiLessonsPkg.dsc @@ -0,0 +1,84 @@ +## +# Copyright (c) 2021, Konstantin Aladyshev +# +# SPDX-License-Identifier: MIT +## + +[Defines] + DSC_SPECIFICATION = 0x0001001C + PLATFORM_GUID = 3db7270f-ffac-4139-90a4-0ae68f3f8167 + PLATFORM_VERSION = 0.01 + PLATFORM_NAME = UefiLessonsPkg + SKUID_IDENTIFIER = DEFAULT + SUPPORTED_ARCHITECTURES = X64 + BUILD_TARGETS = RELEASE + + +[LibraryClasses] + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + #PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + #SimpleLibrary|UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf + #SimpleLibrary|UefiLessonsPkg/Library/SimpleLibraryWithConstructor/SimpleLibraryWithConstructor.inf + SimpleLibrary|UefiLessonsPkg/Library/SimpleLibraryWithConstructorAndDestructor/SimpleLibraryWithConstructorAndDestructor.inf + +[Components] + UefiLessonsPkg/SimplestApp/SimplestApp.inf + UefiLessonsPkg/HelloWorld/HelloWorld.inf + UefiLessonsPkg/ImageHandle/ImageHandle.inf + UefiLessonsPkg/ImageInfo/ImageInfo.inf + UefiLessonsPkg/MemoryInfo/MemoryInfo.inf + UefiLessonsPkg/SimpleShellApp/SimpleShellApp.inf + UefiLessonsPkg/ListVariables/ListVariables.inf + UefiLessonsPkg/ShowBootVariables/ShowBootVariables.inf + UefiLessonsPkg/InteractiveApp/InteractiveApp.inf + UefiLessonsPkg/PCDLesson/PCDLesson.inf + UefiLessonsPkg/SmbiosInfo/SmbiosInfo.inf + UefiLessonsPkg/ShowTables/ShowTables.inf + UefiLessonsPkg/AcpiInfo/AcpiInfo.inf + UefiLessonsPkg/SaveBGRT/SaveBGRT.inf + UefiLessonsPkg/ListPCI/ListPCI.inf + UefiLessonsPkg/SimpleDriver/SimpleDriver.inf + UefiLessonsPkg/PCIRomInfo/PCIRomInfo.inf + UefiLessonsPkg/Library/SimpleLibrary/SimpleLibrary.inf + UefiLessonsPkg/Library/SimpleLibraryWithConstructor/SimpleLibraryWithConstructor.inf + UefiLessonsPkg/SimpleLibraryUser/SimpleLibraryUser.inf + UefiLessonsPkg/SimpleClassProtocol/SimpleClassProtocol.inf + UefiLessonsPkg/SimpleClassUser/SimpleClassUser.inf + UefiLessonsPkg/HotKeyDriver/HotKeyDriver.inf + UefiLessonsPkg/ShowHII/ShowHII.inf + UefiLessonsPkg/HIIStringsC/HIIStringsC.inf + UefiLessonsPkg/HIIStringsUNI/HIIStringsUNI.inf + UefiLessonsPkg/HIIStringsUNIRC/HIIStringsUNIRC.inf + UefiLessonsPkg/HIIStringsMan/HIIStringsMan.inf + UefiLessonsPkg/HIIAddRussianFont/HIIAddRussianFont.inf + UefiLessonsPkg/HIIAddLocalization/HIIAddLocalization.inf + UefiLessonsPkg/AddNewLanguage/AddNewLanguage.inf + UefiLessonsPkg/HIISimpleForm/HIISimpleForm.inf + UefiLessonsPkg/HIIStaticForm/HIIStaticForm.inf + UefiLessonsPkg/HIIStaticFormDriver/HIIStaticFormDriver.inf + UefiLessonsPkg/DisplayHIIByGuid/DisplayHIIByGuid.inf + UefiLessonsPkg/SetVariableExample/SetVariableExample.inf + UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf + +[PcdsFixedAtBuild] + gUefiLessonsPkgTokenSpaceGuid.PcdMyVar32_2|44 + diff --git a/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.c b/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.c new file mode 100644 index 0000000..e926514 --- /dev/null +++ b/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2021, Konstantin Aladyshev + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include + +VOID Usage() +{ + Print(L"Recalculate CRCs for dmpstore command dump\n"); + Print(L"\n"); + Print(L" UpdateDmpstoreDump \n"); +} + +INTN EFIAPI ShellAppMain(IN UINTN Argc, IN CHAR16 **Argv) +{ + if (Argc!=2) { + Usage(); + return EFI_INVALID_PARAMETER; + } + + SHELL_FILE_HANDLE FileHandle; + + CHAR16* Filename = Argv[1]; + EFI_STATUS Status = ShellOpenFileByName( + Filename, + &FileHandle, + EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't open file %s\n", Filename); + return Status; + } + + UINT64 FileSize; + Status = ShellGetFileSize(FileHandle, &FileSize); + if (EFI_ERROR(Status)) { + Status = ShellCloseFile(&FileHandle); + return SHELL_DEVICE_ERROR; + } + + UINT64 FilePos = 0; + while (FilePos < FileSize) { + UINTN ToReadSize; + UINT32 NameSize; + ToReadSize = sizeof(NameSize); + Status = ShellReadFile(FileHandle, &ToReadSize, &NameSize); + if (EFI_ERROR(Status) || (ToReadSize != sizeof(NameSize))) { + Status = SHELL_VOLUME_CORRUPTED; + break; + } + FilePos += ToReadSize; + + UINT32 DataSize; + ToReadSize = sizeof(DataSize); + Status = ShellReadFile(FileHandle, &ToReadSize, &DataSize); + if (EFI_ERROR(Status) || (ToReadSize != sizeof(DataSize))) { + Status = SHELL_VOLUME_CORRUPTED; + break; + } + FilePos += ToReadSize; + + UINTN RemainingSize = NameSize + + sizeof(EFI_GUID) + + sizeof(UINT32) + + DataSize; + UINT8* Buffer = AllocatePool(sizeof(NameSize) + sizeof(DataSize) + RemainingSize); + if (Buffer == NULL) { + Status = SHELL_OUT_OF_RESOURCES; + break; + } + + *(UINT32*)Buffer = NameSize; + *((UINT32*)Buffer + 1) = DataSize; + + ToReadSize = RemainingSize; + Status = ShellReadFile(FileHandle, &ToReadSize, (UINT32*)Buffer + 2); + if (EFI_ERROR(Status) || (ToReadSize != RemainingSize)) { + Status = SHELL_VOLUME_CORRUPTED; + FreePool (Buffer); + break; + } + FilePos += ToReadSize; + + + UINT32 Crc32; + gBS->CalculateCrc32 ( + Buffer, + sizeof(NameSize) + sizeof(DataSize) + RemainingSize, + &Crc32 + ); + + UINTN ToWriteSize = sizeof(Crc32); + Status = ShellWriteFile( + FileHandle, + &ToWriteSize, + &Crc32 + ); + if (EFI_ERROR(Status) || (ToWriteSize != sizeof(Crc32))) { + Print(L"Error! Not all data was written\n"); + FreePool(Buffer); + break; + } + FilePos += ToWriteSize; + FreePool(Buffer); + } + + if (EFI_ERROR(Status)) { + Print(L"Error! %r\n", Status); + } + + Status = ShellCloseFile(&FileHandle); + if (EFI_ERROR(Status)) { + Print(L"Can't close file: %r\n", Status); + } + + return EFI_SUCCESS; +} diff --git a/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf b/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf new file mode 100644 index 0000000..eef23cc --- /dev/null +++ b/Lessons/Lesson_61/UefiLessonsPkg/UpdateDmpstoreDump/UpdateDmpstoreDump.inf @@ -0,0 +1,26 @@ +## +# Copyright (c) 2021, Konstantin Aladyshev +# +# SPDX-License-Identifier: MIT +## + +[Defines] + INF_VERSION = 1.25 + BASE_NAME = UpdateDmpstoreDump + FILE_GUID = d14fe21b-7dbf-40ff-96cb-5d6f5b63cda6 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = ShellCEntryLib + +[Sources] + UpdateDmpstoreDump.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + ShellCEntryLib + ShellLib diff --git a/Lessons/Lesson_61/bootorder.png b/Lessons/Lesson_61/bootorder.png new file mode 100644 index 0000000..242d2b5 Binary files /dev/null and b/Lessons/Lesson_61/bootorder.png differ diff --git a/Lessons/Lesson_61/hexedit_1.png b/Lessons/Lesson_61/hexedit_1.png new file mode 100644 index 0000000..95d8def Binary files /dev/null and b/Lessons/Lesson_61/hexedit_1.png differ diff --git a/Lessons/Lesson_61/hexedit_2.png b/Lessons/Lesson_61/hexedit_2.png new file mode 100644 index 0000000..2048428 Binary files /dev/null and b/Lessons/Lesson_61/hexedit_2.png differ diff --git a/Lessons/Lesson_61/hexedit_3.png b/Lessons/Lesson_61/hexedit_3.png new file mode 100644 index 0000000..b5204ae Binary files /dev/null and b/Lessons/Lesson_61/hexedit_3.png differ diff --git a/Lessons/Lesson_61/hexedit_help.png b/Lessons/Lesson_61/hexedit_help.png new file mode 100644 index 0000000..fc04e4c Binary files /dev/null and b/Lessons/Lesson_61/hexedit_help.png differ -- cgit v1.2.3-18-g5258