SIMPLE_FONT package in OptionROM code


Konstantin Aladyshev
 

Hello!

Currently I develop an OptionROM for a custom PCI-E device.
In this OptionROM I want to publish a HII form for the device
configuration. Therefore I use the "HiiAddPackages" in the driver's
"EFI_DRIVER_BINDING_PROTOCOL.Start()" function. And everything works fine.

Now I want to use my local language in the OptionROM form. The problem is
that my local language is not very often implemented in the UEFI Firmware
by default.
For these cases I've decided to publish the "SIMPLE_FONT" HII package with
my language glyphs directly from the OptionROM code.
And it worked fine until I noticed that UEFI firmware on different
motherboards has different font saturation.

For example here are pseudo-graphics for the "1" code glyph in AMI and
InsydeH2O firmware:

AMI

0x0031
--------
--------
--------
--------
--------
----X---
---XX---
--X-X---
----X---
----X---
----X---
----X---
----X---
----X---
--XXXXX-
--------
--------
--------
--------

Insyde H2O

0x0031
--------
--------
--------
--------
---XX---
-XXXX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
--------
--------
--------

This gives me a problem, what font saturation should I use in
my SIMPLE_FONT package. In any choice it would look good on some
motherboards, but bad on others.
I'm thinking that I should get some glyph bitmap and based on its
saturation publish one font version or another. How can I do it?
Or is there any other solution to this problem?

Best regards,
Konstantin Aladyshev


Felix Polyudov
 

There is no standard way to query platform glyph styles.
Overall, list of supported languages is typically a property of the system firmware.
If system firmware does not support the language you need, there likely will be no way for the end user to switch to the language even if your OpROM driver supports it.
On the other hand, if system firmware does support the language and the language is alphabet-based the font package should already be available.
Your driver just needs to publish the string package.

-----Original Message-----
From: discuss@edk2.groups.io <discuss@edk2.groups.io> On Behalf Of Konstantin Aladyshev via groups.io
Sent: Thursday, January 19, 2023 8:29 AM
To: discuss <discuss@edk2.groups.io>
Subject: [EXTERNAL] [edk2-discuss] SIMPLE_FONT package in OptionROM code


**CAUTION: The e-mail below is from an external source. Please exercise caution before opening attachments, clicking links, or following guidance.**

Hello!

Currently I develop an OptionROM for a custom PCI-E device.
In this OptionROM I want to publish a HII form for the device configuration. Therefore I use the "HiiAddPackages" in the driver's "EFI_DRIVER_BINDING_PROTOCOL.Start()" function. And everything works fine.

Now I want to use my local language in the OptionROM form. The problem is that my local language is not very often implemented in the UEFI Firmware by default.
For these cases I've decided to publish the "SIMPLE_FONT" HII package with my language glyphs directly from the OptionROM code.
And it worked fine until I noticed that UEFI firmware on different motherboards has different font saturation.

For example here are pseudo-graphics for the "1" code glyph in AMI and InsydeH2O firmware:

AMI

0x0031
--------
--------
--------
--------
--------
----X---
---XX---
--X-X---
----X---
----X---
----X---
----X---
----X---
----X---
--XXXXX-
--------
--------
--------
--------

Insyde H2O

0x0031
--------
--------
--------
--------
---XX---
-XXXX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
--------
--------
--------

This gives me a problem, what font saturation should I use in my SIMPLE_FONT package. In any choice it would look good on some motherboards, but bad on others.
I'm thinking that I should get some glyph bitmap and based on its saturation publish one font version or another. How can I do it?
Or is there any other solution to this problem?

Best regards,
Konstantin Aladyshev





-The information contained in this message may be confidential and proprietary to American Megatrends (AMI). This communication is intended to be read only by the individual or entity to whom it is addressed or by their designee. If the reader of this message is not the intended recipient, you are on notice that any distribution of this message, in any form, is strictly prohibited. Please promptly notify the sender by reply e-mail or by telephone at 770-246-8600, and then delete or destroy all copies of the transmission.


Konstantin Aladyshev
 

Hi Felix!

Thanks for the response!

I was able to solve my problem using the `GetGlyph` function from the
`gEfiHiiFontProtocolGuid` protocol. This function can return a `Blt` of the
glyph.

Here is the example app that I've used to test how 'T' glyph is displayed
on different UEFI firmwares:
```cpp
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_HII_FONT_PROTOCOL *gHiiFont = NULL;
EFI_STATUS Status = gBS->LocateProtocol(&gEfiHiiFontProtocolGuid,
NULL,
(VOID **)&gHiiFont);
if (EFI_ERROR(Status)) {
Print(L"Error! Can't get gEfiHiiFontProtocolGuid\n");
return Status;
}

EFI_IMAGE_OUTPUT* Blt = NULL;
UINTN Baseline;
Status = gHiiFont->GetGlyph(gHiiFont, L'T', NULL, &Blt, &Baseline);
if (EFI_ERROR(Status)) {
Print(L"Error! GetGlyph returned %r\n", Status);
return Status;
}

for (UINT8 i = 0; i < (Blt->Height); i++) {
for (UINT8 j = 0; j < (Blt->Width); j++) {
Print(L"%02x", Blt->Image.Bitmap[i*(Blt->Width) + j].Blue);
Print(L"%02x", Blt->Image.Bitmap[i*(Blt->Width) + j].Green);
Print(L"%02x", Blt->Image.Bitmap[i*(Blt->Width) + j].Red);
Print(L" ");
}
Print(L"\n");
}
return EFI_SUCCESS;
}
```

This output either something like
```
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 989898 989898 989898 989898 989898 989898 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 989898 989898 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
```
or
```
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 989898 989898 989898 989898 989898 989898 989898
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 989898 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
000000 000000 000000 000000 000000 000000 000000 000000
```
Therefore `IsBoldFont` function can be written like this:
```cpp
BOOLEAN IsBoldFont()
{
EFI_HII_FONT_PROTOCOL *gHiiFont = NULL;
EFI_STATUS Status = gBS->LocateProtocol(&gEfiHiiFontProtocolGuid,
NULL,
(VOID **)&gHiiFont);
if (EFI_ERROR(Status)) {
return FALSE;
}

EFI_IMAGE_OUTPUT* Blt = NULL;
UINTN Baseline;
Status = gHiiFont->GetGlyph(gHiiFont, L'T', NULL, &Blt, &Baseline);
if (EFI_ERROR(Status)) {
return FALSE;
}

UINTN Pixels = 0;
for (UINT8 i = 0; i < (Blt->Width); i++) {
if ((Blt->Image.Bitmap[10*(Blt->Width) + i].Blue != 0x00) ||
(Blt->Image.Bitmap[10*(Blt->Width) + i].Green != 0x00) ||
(Blt->Image.Bitmap[10*(Blt->Width) + i].Red != 0x00)) {
Pixels++;
}
}
if (Pixels > 1) {
return TRUE;
}

return FALSE;
}
```

Based on its output I populate either bold or standard font.
_________________________

Conclusion:
I understand that all of this is probably not an UEFI way. Doing things the
right way I just need to supply strings in `UNI` in english and my local
language, and hope for the local language support in the firmware. But
what's fun about that?)
Maybe I'll fallback to this, but right now I've tested my solution and it
performs well on all available to me motherboards.

On Wed, Jan 25, 2023 at 2:38 AM Felix Polyudov <Felixp@...> wrote:

There is no standard way to query platform glyph styles.
Overall, list of supported languages is typically a property of the system
firmware.
If system firmware does not support the language you need, there likely
will be no way for the end user to switch to the language even if your
OpROM driver supports it.
On the other hand, if system firmware does support the language and the
language is alphabet-based the font package should already be available.
Your driver just needs to publish the string package.

-----Original Message-----
From: discuss@edk2.groups.io <discuss@edk2.groups.io> On Behalf Of
Konstantin Aladyshev via groups.io
Sent: Thursday, January 19, 2023 8:29 AM
To: discuss <discuss@edk2.groups.io>
Subject: [EXTERNAL] [edk2-discuss] SIMPLE_FONT package in OptionROM code


**CAUTION: The e-mail below is from an external source. Please exercise
caution before opening attachments, clicking links, or following guidance.**

Hello!

Currently I develop an OptionROM for a custom PCI-E device.
In this OptionROM I want to publish a HII form for the device
configuration. Therefore I use the "HiiAddPackages" in the driver's
"EFI_DRIVER_BINDING_PROTOCOL.Start()" function. And everything works fine.

Now I want to use my local language in the OptionROM form. The problem is
that my local language is not very often implemented in the UEFI Firmware
by default.
For these cases I've decided to publish the "SIMPLE_FONT" HII package with
my language glyphs directly from the OptionROM code.
And it worked fine until I noticed that UEFI firmware on different
motherboards has different font saturation.

For example here are pseudo-graphics for the "1" code glyph in AMI and
InsydeH2O firmware:

AMI

0x0031
--------
--------
--------
--------
--------
----X---
---XX---
--X-X---
----X---
----X---
----X---
----X---
----X---
----X---
--XXXXX-
--------
--------
--------
--------

Insyde H2O

0x0031
--------
--------
--------
--------
---XX---
-XXXX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
---XX---
--------
--------
--------

This gives me a problem, what font saturation should I use in my
SIMPLE_FONT package. In any choice it would look good on some motherboards,
but bad on others.
I'm thinking that I should get some glyph bitmap and based on its
saturation publish one font version or another. How can I do it?
Or is there any other solution to this problem?

Best regards,
Konstantin Aladyshev





-The information contained in this message may be confidential and
proprietary to American Megatrends (AMI). This communication is intended to
be read only by the individual or entity to whom it is addressed or by
their designee. If the reader of this message is not the intended
recipient, you are on notice that any distribution of this message, in any
form, is strictly prohibited. Please promptly notify the sender by reply
e-mail or by telephone at 770-246-8600, and then delete or destroy all
copies of the transmission.