On 01/23/20 22:08, Andrew Fish wrote:
>
>> On Jan 23, 2020, at 3:21 AM, Laszlo Ersek <ler...@redhat.com> wrote:
>>
>> Hi Ken,
>>
>> On 01/23/20 02:37, Ken Taylor wrote:
>>
>>> If I try to get the size of a DynamicEx PCD in the context of a BIOS
>>> build for which that PCD is undefined, the call locks up.  I
>>> expected to just get a size of 0, since the PCD is not defined in
>>> the build context of the PCD DXE service.  Is this a problem that's
>>> been fixed since my BIOS source code was cut?  What can I do for
>>> older builds that haven't been fixed (and probably never will)?  Do
>>> I have to just accept that I'm going to get garbage or lockup if I
>>> run my shell utility on some builds?  Do I have to write a DXE
>>> driver and expose a protocol, just so I can know if that PCD exists
>>> and is properly defined?
>>
>> I think the ASSERT() that you run into is the one in
>> GetExPcdTokenNumber(), file
>> "MdeModulePkg/Universal/PCD/Dxe/Service.c":
>>
>>>  MatchGuid   = ScanGuid (GuidTable, mDxeGuidTableSize, Guid);
>>>  //
>>>  // We need to ASSERT here. If GUID can't be found in GuidTable, this is a
>>>  // error in the BUILD system.
>>>  //
>>>  ASSERT (MatchGuid != NULL);
>>
>> Can you try the following:
>>
>> - Locate EFI_PCD_PROTOCOL.
>>
>> - Call EFI_PCD_PROTOCOL.GetNextTokenSpace() in a loop, until you find
>>  the GUID of your own token space GUID, or the function returns an
>>  error.
>>
>> - If your token space GUID has been found, call PcdGetEx8().
>>
>
> Laszlo,
>
> I think it may be better to call PCD_PROTOCOL.GetNextToken() as the
> GUID and Token spaces are both sparse name spaces. The Get*Ex()
> functions don't return errors so I guess this is your only choice.

I agree.

I've been thinking about a way to identify the token value that we need
to stop at, when enumerating the existing tokens (in the already-found
vendor GUID token space). It looks like we need to do three things:

- first check whether the vendor token namespace GUID is known by the
  platform (using the above-quoted EFI_PCD_PROTOCOL.GetNextTokenSpace()
  loop),

- if so, call PcdTokenEx (Guid,TokenName); save the return value

- call EFI_PCD_PROTOCOL.GetNextToken (Guid, &TokenNumber) in a loop,
  until it finishes with EFI_NOT_FOUND, or the desired token number is
  found

- then call PcdGetEx8().

> You could probably make a MyLibGet*Ex() function that returns
> EFI_STATUS, and returns the data via an arg.   MyLibGet*Ex() could
> abstract the PCD_PROTOCOL.GetNextToken() check, and it could also
> probably abstract grabbing the protocol.
>
> FYI it looks like the function header is much more description for
> GetNextToken() in PCD_PROTOCOL [1] vs EFI_PCD_PROTOCOL [2]. Also
> EFI_PCD_PROTOCOL does not have the *Ex functions, so you need
> PCD_PROTOCOL anyway to have access to the *Ex versions of the API.

EFI_PCD_PROTOCOL is the portable (PI standard) protocol, and I do think
it provides access to the DynamicEx (i.e., GUID-ed) PCDs. What
EFI_PCD_PROTOCOL does not provide access to is the *non-Ex* (i.e.,
GUID-less) Dynamic PCDs.

When I browsed the PCD DXE driver yesterday, this confused me hugely.
The names of the EFI_PCD_PROTOCOL member functions do not *say* "Ex",
but they do *mean* "Ex" -- they take GUID parameters.

We can compare the MdePkg/Library/DxePcdLib implementations of
LibPcdGet8() and LibPcdGetEx8():

> UINT8
> EFIAPI
> LibPcdGet8 (
>   IN UINTN             TokenNumber
>   )
> {
>   return GetPcdProtocol()->Get8 (TokenNumber);
> }

vs.

> UINT8
> EFIAPI
> LibPcdGetEx8 (
>   IN CONST GUID        *Guid,
>   IN UINTN             TokenNumber
>   )
> {
>   ASSERT (Guid != NULL);
>
>   return GetPiPcdProtocol()->Get8 (Guid, TokenNumber);
> }

The non-Ex version calls GetPcdProtocol(), which returns PCD_PROTOCOL.
Then we call PCD_PROTOCOL.Get8(). To that, we don't pass a GUID.

The Ex version calls GetPiPcdProtocol), which returns EFI_PCD_PROTOCOL.
Then we call EFI_PCD_PROTOCOL.Get8(). To that, we do pass a GUID -- in
spite of the member name not containing "Ex".

And then, we can check both protocol member implementations in
"MdeModulePkg/Universal/PCD/Dxe/Pcd.c":

- "mPcdInstance" is of type PCD_PROTOCOL, and "mPcdInstance.Get8" points
  to DxePcdGet8(),

- "mEfiPcdInstance" is of type EFI_PCD_PROTOCOL, and
  "mEfiPcdInstance.Get8" points to DxePcdGet8Ex().

DxePcdGet8() only takes a TokenNumber, DxePcdGet8Ex() takes both Guid
and ExTokenNumber.

So I guess, when PCD_PROTOCOL got standardized for the PI spec, as
EFI_PCD_PROTOCOL, people must have said, 'we don't need no stinky
GUID-less PCD access -- and then, why state "Ex" in the member names, if
"Ex" is the *only* way anyway?'

I do find it strange though that, as you say, there seem to be no
"PcdLib.h" interfaces that look up both the GUID and the TokenNumber
automatically, return RETURN_NOT_FOUND if either is absent, and store
the value to an output parameter otherwise.

(While we do have LibPcdSetXxxS() functions -- note the trailing "S" --
that return status values, those don't seem to cope with missing GUID or
TokenNumber either.)

Thanks!
Laszlo


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#53470): https://edk2.groups.io/g/devel/message/53470
Mute This Topic: https://groups.io/mt/70044584/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to