From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-yb1-f181.google.com (mail-yb1-f181.google.com [209.85.219.181]) by mx.groups.io with SMTP id smtpd.web12.247.1611941481634417026 for ; Fri, 29 Jan 2021 09:31:21 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@waymo.com header.s=20200102 header.b=RI73c1ot; spf=pass (domain: google.com, ip: 209.85.219.181, mailfrom: wonderfly@google.com) Received: by mail-yb1-f181.google.com with SMTP id k4so9661430ybp.6 for ; Fri, 29 Jan 2021 09:31:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waymo.com; s=20200102; h=mime-version:references:in-reply-to:reply-to:from:date:message-id :subject:to; bh=noVXhjigRSRWP3XtUdNPro9/itcGfVVU2W2GM68wC60=; b=RI73c1otK97qoT4rmV0ERSA0oOxe6S/oe1E3QqQMjwm1vgBy8co7PF0AJOqxvKIGeC flL5WVg8z8Hy6DiYw7UYM8ikvp7TH/vvrtKwc4olLQ+1THS2tRw7dOSFq6fEuBE0vkW4 wy/vgmijo921Do6s3+TkkiQvK8+6mY/FMKxUizdzL/6zQTwcrOj3muuGCY55je++kZVF RbKpztp5L43/LrnaSHkocVMgehcJ7b5TtdroWch7vd2MEWTTBBc2uzW+I2y76SflV70a QRpIJEnet1sL0+TK3ZrhDfhSO3TKZ4X5pQ3F0mh6mzR2L7jsaznvlOSQGp3eQUzGu/GY 6j4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:reply-to :from:date:message-id:subject:to; bh=noVXhjigRSRWP3XtUdNPro9/itcGfVVU2W2GM68wC60=; b=ebJvAkaBkrVsa93lIfEHbGwVe6vqlX00OdnwVHTtVg0Lr/usOvvdWeKqI6vN2J3z+P 6rdgPaSgP+AwTMUYIQudUfKJnf2rAmMisRNHril7y5AcYy8V47flSCeCcN1Tiy3K5ncI onNly2MNCQnZ+I3S5MraNeYq/UgwtEvGq3wiXHX3wkoKJFe+cjZJS0hjtaPr1HhBUilq HeaDIVqydBrLMz4RKh830ug2cHOIars71GBjM6BkcTQHcFH4TosCLloGHsiQAuzTXctx ZXCM0ShYHPyw7tCzSvTlVzTcf01IG77XiUlK5k3F7xUP2S8KeBBfGU8H7Brlaz//OuW/ qoRQ== X-Gm-Message-State: AOAM5312D4mOqeMo/8ZguM+DDKoGKy80uisbO4ApZbzdgZa3Q31eml4x 8rwrRTkellpYPofHd3SxqIUJ0+mK3G80g+V/XIzcO2PLJKk= X-Google-Smtp-Source: ABdhPJzljDiRHpuzk8VmuZIa9TDN7rbOq7T1OhlO8XiHnY69gfPHNZ8aVtls/gJlFAij4rvAiXUHHEdjr/LRUOZI3cs= X-Received: by 2002:a25:e013:: with SMTP id x19mr7498474ybg.122.1611941480523; Fri, 29 Jan 2021 09:31:20 -0800 (PST) MIME-Version: 1.0 References: <9vLZ.1611858118289759978.CNuw@groups.io> In-Reply-To: Reply-To: wonderfly@waymo.com From: Daniel Wang Date: Fri, 29 Jan 2021 09:31:09 -0800 Message-ID: Subject: Re: [edk2-devel] What is a "NULL" library class? To: devel@edk2.groups.io, nathaniel.l.desimone@intel.com Content-Type: multipart/alternative; boundary="00000000000058d79a05ba0d5f06" --00000000000058d79a05ba0d5f06 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks for the detailed explanation. Makes sense now. On Thu, Jan 28, 2021 at 5:43 PM Nate DeSimone < nathaniel.l.desimone@intel.com> wrote: > Hi There, > > First of all, welcome! > > So, =E2=80=9CNULL=E2=80=9D library classes are conceptually an "anonymou= s library". It > enables one to statically link code into a module even if the module > doesn't directly call functions in that library. All libraries, both > regular libraries with a declared LibraryClass as well as these anonymou= s > libraries, can publish both a constructor and a destructor. The EDK II > build system will automatically generate a small amount of C code that > invokes all library constructors before the entry point for the module i= s > invoked, and all destructors after the entry point returns. This is usef= ul > for building statically linked plug-ins. > > I think my favorite example of this in-action is the UEFI Shell, here is > what a typical DSC declaration for the UEFI Shell looks like: > > ShellPkg/Application/Shell/Shell.inf { > > gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE > > > NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1Commands= Lib.inf > > NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2Commands= Lib.inf > > NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3Commands= Lib.inf > > NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1Comman= dsLib.inf > > NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1Comm= andsLib.inf > > NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1Commands= Lib.inf > > NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1Comm= andsLib.inf > > NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2Comm= andsLib.inf > > ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib= .inf > > HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsing= Lib.inf > > BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCom= mandLib.inf > > ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.in= f > ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf > } > > If you take a look at > ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.i= nf, > you will see that the constructor for that anonymous library is named > ShellLevel1CommandsLibConstructor(). Now, let's go and look at the > definition for ShellLevel1CommandsLibConstructor() in > ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c > and note the following code snippet: > > ShellCommandRegisterCommandName(L"stall", ShellCommandRunStall ... > ShellCommandRegisterCommandName(L"for", ShellCommandRunFor ... > ShellCommandRegisterCommandName(L"goto", ShellCommandRunGoto ... > ShellCommandRegisterCommandName(L"if", ShellCommandRunIf ... > ShellCommandRegisterCommandName(L"shift", ShellCommandRunShift ... > ShellCommandRegisterCommandName(L"exit", ShellCommandRunExit ... > ShellCommandRegisterCommandName(L"else", ShellCommandRunElse ... > ShellCommandRegisterCommandName(L"endif", ShellCommandRunEndIf ... > ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor ... > > This library is installing new commands into the UEFI shell during its > initialization procedure. This allows one to add custom commands to the > shell as statically linked built-ins. A typical use case would be > implementing platform specific diagnostic/recovery utilities. > > Hope that helps! > Nate > > > From: devel@edk2.groups.io On Behalf Of > wonderfly@waymo.com > > Sent: Thursday, January 28, 2021 10:22 AM > > To: devel@edk2.groups.io > > Subject: [edk2-devel] What is a "NULL" library class? > > > > Hi, > > > > I am super new to EDK2 development so excuse my ignorance. While > browsing the code base I find a lot places where the keyword "NULL" is u= sed > in place of a LibraryClass, specifically in DSC files. For example, > > in edk2/UefiPayloadPkg/UefiPayloadPkgIa32.dsc: > > > MdeModulePkg/Core/Dxe/DxeMain.inf { > > > > > NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressL= ib.inf > > } > > > > What does this mean? Does it mean that the LzmaCustomDecompressLib.in= f > library instance is unconditionally linked for this package? > > > > >=20 > > > --=20 Best, Daniel --00000000000058d79a05ba0d5f06 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Tha= nks for the detailed explanation.=C2=A0 Makes sense now.

On Thu, Jan 2= 8, 2021 at 5:43 PM Nate DeSimone <nathaniel.l.desimone@intel.com> wrote:
Hi There,

First of all, welcome!

So, =E2=80=9CNULL=E2=80=9D library classes are conceptually an "anony= mous library". It enables one to statically link code into a module ev= en if the module doesn't directly call functions in that library. All l= ibraries, both regular libraries with a declared LibraryClass as well as th= ese anonymous libraries, can publish both a constructor and a destructor. T= he EDK II build system will automatically generate a small amount of C code= that invokes all library constructors before the entry point for the modul= e is invoked, and all destructors after the entry point returns. This is us= eful for building statically linked plug-ins.

I think my favorite example of this in-action is the UEFI Shell, here is w= hat a typical DSC declaration for the UEFI Shell looks like:

ShellPkg/Application/Shell/Shell.inf {
=C2=A0 <PcdsFixedAtBuild>
=C2=A0 =C2=A0 gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE =C2=A0 <LibraryClasses>
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLe= vel1CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLe= vel2CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLe= vel3CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellD= river1CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShell= Install1CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDe= bug1CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShell= Network1CommandsLib.inf
=C2=A0 =C2=A0 NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShell= Network2CommandsLib.inf
=C2=A0 =C2=A0 ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShe= llCommandLib.inf
=C2=A0 =C2=A0 HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiH= andleParsingLib.inf
=C2=A0 =C2=A0 BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/Uefi= ShellBcfgCommandLib.inf
=C2=A0 =C2=A0 ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShell= CEntryLib.inf
=C2=A0 =C2=A0 ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
}

If you take a look at ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShel= lLevel1CommandsLib.inf, you will see that the constructor for that anonymou= s library is named ShellLevel1CommandsLibConstructor(). Now, let's go a= nd look at the definition for ShellLevel1CommandsLibConstructor() in ShellP= kg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c and note= the following code snippet:

ShellCommandRegisterCommandName(L"stall",=C2=A0 ShellCommandRunS= tall=C2=A0 =C2=A0...
ShellCommandRegisterCommandName(L"for",=C2=A0 =C2=A0 ShellComman= dRunFor=C2=A0 =C2=A0 =C2=A0...
ShellCommandRegisterCommandName(L"goto",=C2=A0 =C2=A0ShellComman= dRunGoto=C2=A0 =C2=A0 ...
ShellCommandRegisterCommandName(L"if",=C2=A0 =C2=A0 =C2=A0ShellC= ommandRunIf=C2=A0 =C2=A0 =C2=A0 ...
ShellCommandRegisterCommandName(L"shift",=C2=A0 ShellCommandRunS= hift=C2=A0 =C2=A0...
ShellCommandRegisterCommandName(L"exit",=C2=A0 =C2=A0ShellComman= dRunExit=C2=A0 =C2=A0 ...
ShellCommandRegisterCommandName(L"else",=C2=A0 =C2=A0ShellComman= dRunElse=C2=A0 =C2=A0 ...
ShellCommandRegisterCommandName(L"endif",=C2=A0 ShellCommandRunE= ndIf=C2=A0 =C2=A0...
ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor= = =C2=A0 ...

This library is installing new commands into the UEFI shell during its ini= tialization procedure. This allows one to add custom commands to the shell = as statically linked built-ins. A typical use case would be implementing pl= atform specific diagnostic/recovery utilities.

Hope that helps!
Nate

> From: devel= @edk2.groups.io <devel@edk2.groups.io> On Behalf Of wonderfly@waymo.com
> Sent: Thursday, January 28, 2021 10:22 AM
> To: devel@e= dk2.groups.io
> Subject: [edk2-devel] What is a "NULL" library class?
>
> Hi,
>
> I am super new to EDK2 development so excuse my ignorance.=C2=A0 Whil= e browsing the code base I find a lot places where the keyword "NULL&q= uot; is used in place of a LibraryClass, specifically in DSC files.=C2=A0 F= or example,
> in edk2/UefiPayloadPkg/UefiPayloadPkgIa32.dsc:=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0
>=C2=A0 =C2=A0MdeModulePkg/Core/Dxe/DxeMain.inf {
>=C2=A0 =C2=A0 =C2=A0<LibraryClasses>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0NULL|MdeModulePkg/Library/LzmaCustomDecompr= essLib/LzmaCustomDecompressLib.inf
>=C2=A0 =C2=A0}
>
> What does this mean?=C2=A0 Does it mean that the LzmaCustomDecompress= Lib.inf library instance is unconditionally linked for this package?
>







--
Best,
Daniel
--00000000000058d79a05ba0d5f06--