Skip to content

Latest commit

 

History

History

Lesson_47

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Now we can finally register our Package list in the HII database. Here is a description for the NewPackageList one more time:

EFI_HII_DATABASE_PROTOCOL.NewPackageList()

Summary:
Adds the packages in the package list to the HII database.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_DATABASE_NEW_PACK) (
 IN CONST EFI_HII_DATABASE_PROTOCOL *This,
 IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
 IN CONST EFI_HANDLE DriverHandle, OPTIONAL
 OUT EFI_HII_HANDLE *Handle
 );

Parameters:
This		A pointer to the EFI_HII_DATABASE_PROTOCOL instance
PackageList	A pointer to an EFI_HII_PACKAGE_LIST_HEADER structure
DriverHandle	Associate the package list with this EFI handle
Handle		A pointer to the EFI_HII_HANDLE instance
Description	This function adds the packages in the package list to the database and returns a handle. If there is a
		EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will create a
		package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.

We've already filled PackageList array, so we can use this function like this:

  EFI_HII_HANDLE Handle;
  EFI_STATUS Status = gHiiDatabase->NewPackageList(gHiiDatabase, PackageListHdr, NULL, &Handle);
  if (EFI_ERROR(Status))
  {
    Print(L"Can't register HII Package list %g, status = %r\n", gHIIStringsCGuid, Status);
  }

Now when we have EFI_HII_HANDLE Handle for our package list it is time to try to get strings from the HII Database. For this we can utilize GetString from another of HII Database protocols - EFI_HII_STRING_PROTOCOL:

EFI_HII_STRING_PROTOCOL.GetString()

Summary:
Returns information about a string in a specific language, associated with a package list.

Prototype:
typedef
EFI_STATUS
(EFIAPI *EFI_HII_GET_STRING) (
 IN CONST EFI_HII_STRING_PROTOCOL *This,
 IN CONST CHAR8 *Language,
 IN EFI_HII_HANDLE PackageList,
 IN EFI_STRING_ID StringId,
 OUT EFI_STRING String,
 IN OUT UINTN *StringSize,
 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
 );
 
Parameters:
This			A pointer to the EFI_HII_STRING_PROTOCOL instance.
PackageList		The package list in the HII database to search for the specified string.
Language		Points to the language for the retrieved string. Callers of interfaces that require RFC
				4646 language codes to retrieve a Unicode string must use the RFC 4647 algorithm to
				lookup the Unicode string with the closest matching RFC 4646 language code.
StringId		The string’s id, which is unique within PackageList.
String			Points to the new null-terminated string.
StringSize		On entry, points to the size of the buffer pointed to by String, in bytes. On return,
				points to the length of the string, in bytes.
StringFontInfo	Points to a buffer that will be callee allocated and will have the string's font
				information into this buffer. The caller is responsible for freeing this buffer. If the
				parameter is NULL a buffer will not be allocated and the string font information will
				not be returned.

Description:
This function retrieves the string specified by StringId which is associated with the specified
PackageList in the language Language and copies it into the buffer specified by String.

Once again here is a standard UEFI scheme for getting resources of unknown size. First we call GetString with a StringSize=0. The function returns EFI_BUFFER_TOO_SMALL, but fills the StringSize with a necessary value. Then we call GetString one more time, this time with a correct StringSize. As we've included UefiHiiServicesLib in our application we don't need to perform LocateProtocol to find EFI_HII_STRING_PROTOCOL but simply can use gHiiString variable. Here is a function PrintStringFromHiiHandle for printing strings from Package list with a EFI_HII_HANDLE by simply providing string (Id, Language) combination:

EFI_STATUS PrintStringFromHiiHandle(EFI_HII_HANDLE* Handle, CHAR8* Language, UINTN StringId)
{
  EFI_STRING String = NULL;
  UINTN StringSize = 0;
  EFI_STATUS Status = gHiiString->GetString(gHiiString, Language, *Handle, StringId, String, &StringSize, NULL);

  if (Status != EFI_BUFFER_TOO_SMALL) {
    return Status;
  }

  String = AllocateZeroPool(StringSize);
  if (String == NULL) {
    return Status;
  }

  Status = gHiiString->GetString(gHiiString, Language, *Handle, StringId, String, &StringSize, NULL);

  Print(L"Status = %r, %s\n", Status, String);

  FreePool(String);

  return EFI_SUCCESS;
}

After we've registered our package we can use it as simple as this:

  PrintStringFromHiiHandle(&Handle, "en-US", 1);
  PrintStringFromHiiHandle(&Handle, "en-US", 2);
  PrintStringFromHiiHandle(&Handle, "fr-FR", 1);
  PrintStringFromHiiHandle(&Handle, "fr-FR", 2);

Now it is time to combine everything together and build our application.

If we execute it under OVMF we would get:

FS0:\> HIIStringsC.efi
Status = Success, English
Status = Success, Hello
Status = Success, French
Status = Success, Bonjour

So everything works correctly!

We can even see our newly created package if we execute our ShowHII application:

FS0:\> ShowHII.efi
...
PackageList[20]: GUID=8E0B8ED3-14F7-499D-A224-AEE89DC97FA3; size=0xC0
        Package[0]: type=STRINGS; size=0x53
        Package[1]: type=STRINGS; size=0x55
        Package[2]: type=END; size=0x4

Keep in mind that if we will try to execute the HIIStringsC app again we would get an errror:

FS0:\> HIIStringsC.efi
Can't register HII Package list 8E0B8ED3-14F7-499D-A224-AEE89DC97FA3, status = Invalid Parameter

It is happening, because it is not possible to register two Package lists with the same GUID.