public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: Andrew Fish <afish@apple.com>, devel@edk2.groups.io
Cc: Ken_Taylor@phoenix.com
Subject: Re: [edk2-devel] PCD EX interface.
Date: Fri, 24 Jan 2020 11:14:24 +0100	[thread overview]
Message-ID: <54362b07-c55e-c9f9-1f5d-86848f769384@redhat.com> (raw)
In-Reply-To: <5D2A47A2-6DCE-448B-A5BA-14BE7BBA464B@apple.com>

On 01/23/20 22:08, Andrew Fish wrote:
>
>> On Jan 23, 2020, at 3:21 AM, Laszlo Ersek <lersek@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


      reply	other threads:[~2020-01-24 10:14 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-23  1:37 PCD EX interface Ken Taylor
2020-01-23 11:21 ` [edk2-devel] " Laszlo Ersek
2020-01-23 21:08   ` Andrew Fish
2020-01-24 10:14     ` Laszlo Ersek [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54362b07-c55e-c9f9-1f5d-86848f769384@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox