aboutsummaryrefslogtreecommitdiffstats
path: root/Lesson_29/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'Lesson_29/README.md')
-rw-r--r--Lesson_29/README.md427
1 files changed, 0 insertions, 427 deletions
diff --git a/Lesson_29/README.md b/Lesson_29/README.md
deleted file mode 100644
index 1b613e7..0000000
--- a/Lesson_29/README.md
+++ /dev/null
@@ -1,427 +0,0 @@
-In the last lesson we've discovered that our system has BGRT ACPI table.
-
-According to the ACPI specification:
-```
-The Boot Graphics Resource Table (BGRT) is an optional table that provides a mechanism to indicate that
-an image was drawn on the screen during boot, and some information about the image.
-The table is written when the image is drawn on the screen. This should be done after it is expected that
-any firmware components that may write to the screen are done doing so and it is known that the image
-is the only thing on the screen. If the boot path is interrupted (e.g., by a key press), the valid bit within the
-status field should be changed to 0 to indicate to the OS that the current image is invalidated
-```
-This table actually have a pointer to image data, check structure definition under https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/Acpi63.h:
-```
-///
-/// Boot Graphics Resource Table definition.
-///
-typedef struct {
- EFI_ACPI_DESCRIPTION_HEADER Header;
- ///
- /// 2-bytes (16 bit) version ID. This value must be 1.
- ///
- UINT16 Version;
- ///
- /// 1-byte status field indicating current status about the table.
- /// Bits[7:1] = Reserved (must be zero)
- /// Bit [0] = Valid. A one indicates the boot image graphic is valid.
- ///
- UINT8 Status;
- ///
- /// 1-byte enumerated type field indicating format of the image.
- /// 0 = Bitmap
- /// 1 - 255 Reserved (for future use)
- ///
- UINT8 ImageType;
- ///
- /// 8-byte (64 bit) physical address pointing to the firmware's in-memory copy
- /// of the image bitmap.
- ///
- UINT64 ImageAddress;
- ///
- /// A 4-byte (32-bit) unsigned long describing the display X-offset of the boot image.
- /// (X, Y) display offset of the top left corner of the boot image.
- /// The top left corner of the display is at offset (0, 0).
- ///
- UINT32 ImageOffsetX;
- ///
- /// A 4-byte (32-bit) unsigned long describing the display Y-offset of the boot image.
- /// (X, Y) display offset of the top left corner of the boot image.
- /// The top left corner of the display is at offset (0, 0).
- ///
- UINT32 ImageOffsetY;
-} EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE;
-```
-
-
-Let's create an app that would save an image from BGRT.
-
-This time to get BGRT table we would utilize `EFI_ACPI_SDT_PROTOCOL` protocol.
-
-To get ACPI table data we would use `GetAcpiTable()` function from this protocol:
-```
-EFI_ACPI_SDT_PROTOCOL.GetAcpiTable()
-
-Summary:
-Returns a requested ACPI table.
-
-Prototype:
-typedef
-EFI_STATUS
-(EFIAPI *EFI_ACPI_GET_ACPI_TABLE) (
- IN UINTN Index,
- OUT EFI_ACPI_SDT_HEADER **Table,
- OUT EFI_ACPI_TABLE_VERSION *Version,
- OUT UINTN *TableKey
- );
-
-Parameters:
-Index The zero-based index of the table to retrieve.
-Table Pointer for returning the table buffer.
-Version On return, updated with the ACPI versions to which this table belongs.
-TableKey On return, points to the table key for the specified ACPI system definition table.
-
-Description:
-The GetAcpiTable() function returns a pointer to a buffer containing the ACPI table associated with the Index that was input. The following structures are not considered elements in the list of ACPI tables:
-- Root System Description Pointer (RSD_PTR)
-- Root System Description Table (RSDT)
-- Extended System Description Table (XSDT)
-```
-In edk2 it is defined here: https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/AcpiSystemDescriptionTable.h
-
-To get all tables we need to call `GetAcpiTable` with incrementing values for `Index` starting with 0, while function returns `EFI_SUCCESS`.
-
-On every success call we would get a pointer to a common header for a ACPI table:
-```
-typedef struct {
- UINT32 Signature;
- UINT32 Length;
- UINT8 Revision;
- UINT8 Checksum;
- CHAR8 OemId[6];
- CHAR8 OemTableId[8];
- UINT32 OemRevision;
- UINT32 CreatorId;
- UINT32 CreatorRevision;
-} EFI_ACPI_SDT_HEADER;
-```
-
-To use `EFI_ACPI_SDT_PROTOCOL` we need to add include to our file:
-```
-#include <Protocol/AcpiSystemDescriptionTable.h>
-```
-And add protocol to the *.inf file:
-```
-[Protocols]
- gEfiAcpiSdtProtocolGuid
-```
-
-Here is a code finding BGRT ACPI table:
-```
-EFI_ACPI_SDT_PROTOCOL* AcpiSdtProtocol;
-EFI_STATUS Status = gBS->LocateProtocol (
- &gEfiAcpiSdtProtocolGuid,
- NULL,
- (VOID**)&AcpiSdtProtocol
- );
-if (EFI_ERROR (Status)) {
- return Status;
-}
-
-BOOLEAN BGRT_found = FALSE;
-UINTN Index = 0;
-EFI_ACPI_SDT_HEADER* Table;
-EFI_ACPI_TABLE_VERSION Version;
-UINTN TableKey;
-while (TRUE) {
- Status = AcpiSdtProtocol->GetAcpiTable(Index,
- &Table,
- &Version,
- &TableKey
- );
- if (EFI_ERROR(Status)) {
- break;
- }
- if (((CHAR8)((Table->Signature >> 0) & 0xFF) == 'B') &&
- ((CHAR8)((Table->Signature >> 8) & 0xFF) == 'G') &&
- ((CHAR8)((Table->Signature >> 16) & 0xFF) == 'R') &&
- ((CHAR8)((Table->Signature >> 24) & 0xFF) == 'T')) {
- BGRT_found = TRUE;
- break;
- }
- Index++;
-}
-if (!BGRT_found) {
- Print(L"BGRT table is not present in the system\n");
- return EFI_UNSUPPORTED;
-}
-```
-
-Now we need to save an image from BGRT table.
-
-Currently ACPI specification support only BMP image type https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#image-type
-
-So first we check if the type is actually BMP:
-```
-EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE* BGRT = (EFI_ACPI_6_3_BOOT_GRAPHICS_RESOURCE_TABLE*)Table;
-if (BGRT->ImageType == 0) {
- ...
-}
-```
-
-Now we need to actually save a BMP image. BGRT doesn't contain any size for an image, only offset to data: `ImageAddress`.
-
-To get image size we need to look at BMP header.
-
-In edk2 it is defined under https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/Bmp.h:
-```
-typedef struct {
- CHAR8 CharB;
- CHAR8 CharM;
- UINT32 Size;
- UINT16 Reserved[2];
- UINT32 ImageOffset;
- UINT32 HeaderSize;
- UINT32 PixelWidth;
- UINT32 PixelHeight;
- UINT16 Planes; ///< Must be 1
- UINT16 BitPerPixel; ///< 1, 4, 8, or 24
- UINT32 CompressionType;
- UINT32 ImageSize; ///< Compressed image size in bytes
- UINT32 XPixelsPerMeter;
- UINT32 YPixelsPerMeter;
- UINT32 NumberOfColors;
- UINT32 ImportantColors;
-} BMP_IMAGE_HEADER;
-```
-
-Don't forget to include this file in our program:
-```
-#include <IndustryStandard/Bmp.h>
-```
-
-When we know that the image is BMP, we can check its signature (`BM`), parse its size and actually write its data to a file. Here we use `EFI_STATUS WriteFile(CHAR16* FileName, VOID* Data, UINTN* Size)` function to write data to a file, we will define it in a minute:
-```
-BMP_IMAGE_HEADER* BMP = (BMP_IMAGE_HEADER*)(BGRT->ImageAddress);
-
-if ((BMP->CharB != 'B') || (BMP->CharM != 'M')) {
- Print(L"BMP image has wrong signature!\n");
- return EFI_UNSUPPORTED;
-}
-Print(L"BGRT conatins BMP image with %dx%d resolution\n", BMP->PixelWidth, BMP->PixelHeight);
-UINTN Size = BMP->Size;
-Status = WriteFile(L"BGRT.bmp", BMP, &Size);
-if (EFI_ERROR(Status)) {
- Print(L"Error! Can't write BGRT.bmp file\n");
-}
-```
-
-Last time we've used `EFI_SHELL_PROTOCOL` to create a file and write data to it. This time we will try to utilize ShelLib:
-
-https://github.com/tianocore/edk2/blob/master/ShellPkg/Include/Library/ShellLib.h
-
-https://github.com/tianocore/edk2/blob/master/ShellPkg/Library/UefiShellLib/UefiShellLib.c
-
-Again we will need 3 functions: for file open, write and close:
-```
-/**
- This function will open a file or directory referenced by filename.
- If return is EFI_SUCCESS, the Filehandle is the opened file's handle;
- otherwise, the Filehandle is NULL. Attributes is valid only for
- EFI_FILE_MODE_CREATE.
- @param[in] FileName The pointer to file name.
- @param[out] FileHandle The pointer to the file handle.
- @param[in] OpenMode The mode to open the file with.
- @param[in] Attributes The file's file attributes.
- ...
-**/
-
-EFI_STATUS
-EFIAPI
-ShellOpenFileByName(
- IN CONST CHAR16 *FileName,
- OUT SHELL_FILE_HANDLE *FileHandle,
- IN UINT64 OpenMode,
- IN UINT64 Attributes
- );
-```
-```
-/**
- Write data to a file.
- This function writes the specified number of bytes to the file at the current
- file position. The current file position is advanced the actual number of bytes
- written, which is returned in BufferSize. Partial writes only occur when there
- has been a data error during the write attempt (such as "volume space full").
- The file is automatically grown to hold the data if required. Direct writes to
- opened directories are not supported.
- @param[in] FileHandle The opened file for writing.
- @param[in, out] BufferSize On input the number of bytes in Buffer. On output
- the number of bytes written.
- @param[in] Buffer The buffer containing data to write is stored.
- ...
-**/
-
-EFI_STATUS
-EFIAPI
-ShellWriteFile(
- IN SHELL_FILE_HANDLE FileHandle,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer
- );
-```
-```
-/**
- Close an open file handle.
- This function closes a specified file handle. All "dirty" cached file data is
- flushed to the device, and the file is closed. In all cases the handle is
- closed.
- @param[in] FileHandle The file handle to close.
-**/
-
-EFI_STATUS
-EFIAPI
-ShellCloseFile (
- IN SHELL_FILE_HANDLE *FileHandle
- );
-```
-
-Advantage of using `ShellLib` is that now we don't need to find `EFI_SHELL_PROTOCOL` and work with it manually.
-
-
-Our `WriteFile` function would look like this:
-```
-EFI_STATUS WriteFile(CHAR16* FileName, VOID* Data, UINTN* Size)
-{
- SHELL_FILE_HANDLE FileHandle;
- EFI_STATUS Status = ShellOpenFileByName(
- FileName,
- &FileHandle,
- EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,
- 0
- );
- if (!EFI_ERROR(Status)) {
- Print(L"Save it to %s\n", FileName);
- UINTN ToWrite = *Size;
- Status = ShellWriteFile(
- FileHandle,
- Size,
- Data
- );
- if (EFI_ERROR(Status)) {
- Print(L"Can't write file: %r\n", Status);
- }
- if (*Size != ToWrite) {
- Print(L"Error! Not all data was written\n");
- }
- Status = ShellCloseFile(
- &FileHandle
- );
- if (EFI_ERROR(Status)) {
- Print(L"Can't close file: %r\n", Status);
- }
- } else {
- Print(L"Can't open file: %r\n", Status);
- }
- return Status;
-}
-```
-
-To use ShellLib we need to include a header in our program:
-```
-#include <Library/ShellLib.h>
-```
-
-Also we need to add `ShellPkg.dec` to our packages and add `ShellLib` to our library classes:
-```
-[Packages]
- MdePkg/MdePkg.dec
-+ ShellPkg/ShellPkg.dec
-
-[LibraryClasses]
- UefiApplicationEntryPoint
- UefiLib
-+ ShellLib
-```
-Besides that our package `*.dsc` file needs to include a `ShellLib` library class:
-```
-[LibraryClasses]
- ...
- ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
-```
-
-Unfortunately this is not enough, our current build would fail with a message, because `ShellLib` by itself needs another library:
-```
-build.py...
-/home/kostr/tiano/edk2/UefiLessonsPkg/UefiLessonsPkg.dsc(...): error 4000: Instance of library class [FileHandleLib] is not found
-```
-
-To find it use our standard tactic:
-```
-$ grep FileHandleLib -r ./ --include=*.inf | grep LIBRARY_CLASS
-```
-
-In the end we had to add several more LibraryClasses to make our build succeed:
-```
-[LibraryClasses]
- ...
- FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
- HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
- SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
- UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
-```
-
-Build our app and execute it under OVMF:
-```
-FS0:\> SaveBGRT.efi
-BGRT conatins BMP image with 193x58 resolution
-Save it to BGRT.bmp7
-FS0:\>
-```
-
-If you look at the BGRT.bmp picture that are app have produced, it would have the same content as https://raw.githubusercontent.com/tianocore/edk2/master/MdeModulePkg/Logo/Logo.bmp
-
-The file itself wouldn't be the same since BGRT driver don't use an image from flash, but actually grabs a boot screen and transforms it to a BMP image. For the proof checkout how https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c uses `TranslateGopBltToBmp` function from the https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/BaseBmpSupportLib/BmpSupportLib.c library.
-If you find it strange that BGRT grabs a screen instead of using an image from flash, remember how BGRT is defined in ACPI specification:
-```
-The Boot Graphics Resource Table (BGRT) is an optional table that provides a mechanism to indicate that an image was drawn on the screen during boot
-```
-
-The file GUID for binary boot logo image is defined in the file https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Logo/Logo.inf
-```
-FILE_GUID = 7BB28B99-61BB-11D5-9A5D-0090273FC14D
-```
-It is a GUID that is usually used for the Logo image in BIOS. It is even hardcoded to https://github.com/tianocore/edk2/blob/master/BaseTools/Source/Python/Eot/Report.py
-```
-## GenerateFfs() method
-#
-# Generate FFS information
-#
-# @param self: The object pointer
-# @param FfsObj: FFS object after FV image is parsed
-#
-def GenerateFfs(self, FfsObj):
- self.FfsIndex = self.FfsIndex + 1
- if FfsObj is not None and FfsObj.Type in [0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xA]:
- FfsGuid = FfsObj.Guid
- FfsOffset = FfsObj._OFF_
- FfsName = 'Unknown-Module'
- FfsPath = FfsGuid
- FfsType = FfsObj._TypeName[FfsObj.Type]
-
- # Hard code for Binary INF
- if FfsGuid.upper() == '7BB28B99-61BB-11D5-9A5D-0090273FC14D':
- FfsName = 'Logo'
-
- if FfsGuid.upper() == '7E374E25-8E01-4FEE-87F2-390C23C606CD':
- FfsName = 'AcpiTables'
-
- if FfsGuid.upper() == '961578FE-B6B7-44C3-AF35-6BC705CD2B1F':
- FfsName = 'Fat'
- ...
-```
-
-If you want to know how Logo and BGRT are work in edk2, checkout these drivers:
-- https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Library/BootLogoLib/
-- https://github.com/tianocore/edk2/tree/master/MdeModulePkg/Logo/
-- https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/
-- https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Library/BaseBmpSupportLib/
-