From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from loongson.cn (loongson.cn [114.242.206.163]) by mx.groups.io with SMTP id smtpd.web09.3734.1668160141387639000 for ; Fri, 11 Nov 2022 01:49:02 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: loongson.cn, ip: 114.242.206.163, mailfrom: lichao@loongson.cn) Received: from loongson.cn (unknown [10.40.24.149]) by gateway (Coremail) with SMTP id _____8AxTbeKGm5juRYGAA--.7425S3; Fri, 11 Nov 2022 17:48:58 +0800 (CST) Received: from lichao-PC (unknown [10.40.24.149]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxXuCKGm5jHtQQAA--.45541S2; Fri, 11 Nov 2022 17:48:58 +0800 (CST) Date: Fri, 11 Nov 2022 17:48:58 +0800 From: "Chao Li" To: xianglai li Cc: "=?utf-8?Q?devel=40edk2.groups.io?=" , Bibo Mao , Leif Lindholm , Liming Gao , Michael D Kinney Message-ID: In-Reply-To: <192edc8781a4166404787c2c3c5390879c7e5741.1668157715.git.lixianglai@loongson.cn> References: <192edc8781a4166404787c2c3c5390879c7e5741.1668157715.git.lixianglai@loongson.cn> Subject: Re: [edk2-platforms][PATCH V5 12/15] Platform/Loongson: Add Platform Boot Manager Lib. X-Mailer: Mailspring MIME-Version: 1.0 X-CM-TRANSID: AQAAf8CxXuCKGm5jHtQQAA--.45541S2 X-CM-SenderInfo: xolfxt3r6o00pqjv00gofq/1tbiAQAHCGNs6eQZ0AAnsi X-Coremail-Antispam: 1Uk129KBjvAXoWfuryrurWDXr4xXFW8CF18uFg_yoW5Ar48Zo WIkFy8Aw1kKr4xWa4kGr1kGa1xXFnFgwsxXr1vvF1UWanF9w1Ygas8X3Z8t3sxAF1kZ3W7 Ja4fJas3AFWSqF95n29KB7ZKAUJUUUUP529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3Ec02F40Eb7x2x7xS6r1j6r4UMc02F40EFcxC0VAKzVAqx4xG6I80ewAqx4xG64kEw2xG 04xIwI0_Xr0_WrUv73VFW2AGmfu7bjvjm3AaLaJ3UjIYCTnIWjp_UUUOh7kC6x804xWl14 x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0rVWrJVCq3wAFIxvE14AKwVWU JVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84ACjcxK6xIIjxv20xvE14 v26F1j6w1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwA2z4x0Y4vEx4A2jsIE 14v26F4UJVW0owA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_Cr1j6rxdM2kKe7AKxVWUtVW8Zw AS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI0UMc02F40Eb7x2 x7xS6r1j6r4UMc02F40EFcxC0VAKzVAqx4xG6I80ewAqx4xG64kEw2xG04xIwI0_Xr0_Wr 1lYx0E2Ix0cI8IcVAFwI0_Wrv_ZF1lYx0Ex4A2jsIE14v26F4j6r4UJwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l7480Y4vEI4kI2Ix0rVAqx4xJMxkF7I0En4kS14 v26r1q6r43MxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8C rVAFwI0_JrI_JrWlx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtw CIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26F1j6w1UMIIF0xvE2Ix0cI8IcVCY1x02 67AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr 0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU0dH UDUUUUU== Content-Type: multipart/alternative; boundary="636e1a8a_189805c2_1e57b" --636e1a8a_189805c2_1e57b Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Reviewed-by: Chao Li Thanks, Chao -------- On 11=E6=9C=88 11 2022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li wrote: > The Library provides Boot Manager interfaces. > > > > RE=46: https://bugzilla.tianocore.org/show=5Fbug.cgi=3Fid=3D4054 > > > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > --- > .../PlatformBootManagerLib/PlatformBm.c =7C 742 ++++++++++++++++++ > .../PlatformBootManagerLib/PlatformBm.h =7C 112 +++ > .../PlatformBootManagerLib.inf =7C 75 ++ > .../PlatformBootManagerLib/QemuKernel.c =7C 81 ++ > 4 files changed, 1010 insertions(+) > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformB= ootManagerLib/PlatformBm.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformB= ootManagerLib/PlatformBm.h > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformB= ootManagerLib/PlatformBootManagerLib.inf > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/PlatformB= ootManagerLib/QemuKernel.c > > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootMan= agerLib/PlatformBm.c b/Platform/Loongson/LoongArchQemuPkg/Library/Platfor= mBootManagerLib/PlatformBm.c > new file mode 100644 > index 0000000000..eb7f4241f0 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib= /PlatformBm.c > =40=40 -0,0 +1,742 =40=40 > +/** =40file > + Implementation for PlatformBootManagerLib library class interfaces. > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include =22PlatformBm.h=22 > + > +STATIC PLAT=46ORM=5FSERIAL=5FCONSOLE mSerialConsole =3D =7B > + // > + // VENDOR=5FDEVICE=5FPATH SerialDxe > + // > + =7B > + =7B HARDWARE=5FDEVICE=5FPATH, HW=5FVENDOR=5FDP, DP=5FNODE=5FLEN (VEND= OR=5FDEVICE=5FPATH) =7D, > + SERIAL=5FDXE=5F=46ILE=5FGUID > + =7D, > + > + // > + // UART=5FDEVICE=5FPATH Uart > + // > + =7B > + =7B MESSAGING=5FDEVICE=5FPATH, MSG=5FUART=5FDP, DP=5FNODE=5FLEN (UART= =5FDEVICE=5FPATH) =7D, > + 0, // Reserved > + =46ixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate > + =46ixedPcdGet8 (PcdUartDefaultDataBits), // DataBits > + =46ixedPcdGet8 (PcdUartDefaultParity), // Parity > + =46ixedPcdGet8 (PcdUartDefaultStopBits) // StopBits > + =7D, > + > + // > + // VENDOR=5FDE=46INED=5FDEVICE=5FPATH TermType > + // > + =7B > + =7B > + MESSAGING=5FDEVICE=5FPATH, MSG=5FVENDOR=5FDP, > + DP=5FNODE=5FLEN (VENDOR=5FDE=46INED=5FDEVICE=5FPATH) > + =7D > + // > + // Guid to be filled in dynamically > + // > + =7D, > + > + // > + // E=46I=5FDEVICE=5FPATH=5FPROTOCOL End > + // > + =7B > + END=5FDEVICE=5FPATH=5FTYPE, END=5FENTIRE=5FDEVICE=5FPATH=5FSUBTYPE, > + DP=5FNODE=5FLEN (E=46I=5FDEVICE=5FPATH=5FPROTOCOL) > + =7D > +=7D; > + > +STATIC PLAT=46ORM=5FUSB=5FKEYBOARD mUsbKeyboard =3D =7B > + // > + // USB=5FCLASS=5FDEVICE=5FPATH Keyboard > + // > + =7B > + =7B > + MESSAGING=5FDEVICE=5FPATH, MSG=5FUSB=5FCLASS=5FDP, > + DP=5FNODE=5FLEN (USB=5FCLASS=5FDEVICE=5FPATH) > + =7D, > + 0x=46=46=46=46, // VendorId: any > + 0x=46=46=46=46, // ProductId: any > + 3, // DeviceClass: HID > + 1, // DeviceSubClass: boot > + 1 // DeviceProtocol: keyboard > + =7D, > + > + // > + // E=46I=5FDEVICE=5FPATH=5FPROTOCOL End > + // > + =7B > + END=5FDEVICE=5FPATH=5FTYPE, END=5FENTIRE=5FDEVICE=5FPATH=5FSUBTYPE, > + DP=5FNODE=5FLEN (E=46I=5FDEVICE=5FPATH=5FPROTOCOL) > + =7D > +=7D; > + > +/** > + Locate all handles that carry the specified protocol, filter them wit= h a > + callback function, and pass each handle that passes the filter to ano= ther > + callback. > + > + =40param=5Bin=5D ProtocolGuid The protocol to look for. > + > + =40param=5Bin=5D =46ilter The filter function to pass each handle to.= If this > + parameter is NULL, then all handles are processed. > + > + =40param=5Bin=5D Process The callback function to pass each handle to= that > + clears the filter. > +**/ > +VOID > +=46ilterAndProcess ( > + IN E=46I=5FGUID *ProtocolGuid, > + IN =46ILTER=5F=46UNCTION =46ilter OPTIONAL, > + IN CALLBACK=5F=46UNCTION Process > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FHANDLE *Handles; > + UINTN NoHandles; > + UINTN Idx; > + > + Status =3D gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, > + NULL /* SearchKey */, &NoHandles, &Handles); > + if (E=46I=5FERROR (Status)) =7B > + // > + // This is not an error, just an informative condition. > + // > + DEBUG ((DEBUG=5FVERBOSE, =22%a: %g: %r=5Cn=22, =5F=5F=46UNCTION=5F=5F= , ProtocolGuid, > + Status)); > + return; > + =7D > + > + ASSERT (NoHandles > 0); > + for (Idx =3D 0; Idx < NoHandles; ++Idx) =7B > + CHAR16 *DevicePathText; > + STATIC CHAR16 =46allback=5B=5D =3D L=22=22; > + > + // > + // The ConvertDevicePathToText () function handles NULL input transpa= rently. > + // > + DevicePathText =3D ConvertDevicePathToText ( > + DevicePath=46romHandle (Handles=5BIdx=5D), > + =46ALSE, // DisplayOnly > + =46ALSE // AllowShortcuts > + ); > + if (DevicePathText =3D=3D NULL) =7B > + DevicePathText =3D =46allback; > + =7D > + > + if ((=46ilter =3D=3D NULL) > + =7C=7C (=46ilter (Handles=5BIdx=5D, DevicePathText))) > + =7B > + Process (Handles=5BIdx=5D, DevicePathText); > + =7D > + > + if (DevicePathText =21=3D =46allback) =7B > + =46reePool (DevicePathText); > + =7D > + =7D > + gBS->=46reePool (Handles); > +=7D > + > +/** > + This =46ILTER=5F=46UNCTION checks if a handle corresponds to a PCI di= splay device. > + > + =40param Handle The handle to check > + =40param ReportText A pointer to a string at the time of the error. > + > + =40retval TURE THe handle corresponds to a PCI display device. > + =40retval =46ALSE THe handle does not corresponds to a PCI display de= vice. > +**/ > +BOOLEAN > +E=46IAPI > +IsPciDisplay ( > + IN E=46I=5FHANDLE Handle, > + IN CONST CHAR16 *ReportText > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FPCI=5FIO=5FPROTOCOL *PciIo; > + PCI=5FTYPE00 Pci; > + > + Status =3D gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid, > + (VOID**)&PciIo); > + if (E=46I=5FERROR (Status)) =7B > + // > + // This is not an error worth reporting. > + // > + return =46ALSE; > + =7D > + > + Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset *= /, > + sizeof Pci / sizeof (UINT32), &Pci); > + if (E=46I=5FERROR (Status)) =7B > + DEBUG ((DEBUG=5FERROR, =22%a: %s: %r=5Cn=22, =5F=5F=46UNCTION=5F=5F, = ReportText, Status)); > + return =46ALSE; > + =7D > + > + return IS=5FPCI=5FDISPLAY (&Pci); > +=7D > + > +/** > + This CALLBACK=5F=46UNCTION attempts to connect a handle non-recursive= ly, asking > + the matching driver to produce all first-level child handles. > + > + =40param Handle The handle to connect. > + =40param ReportText A pointer to a string at the time of the error. > + > + =40retval VOID > +**/ > +VOID > +E=46IAPI > +Connect ( > + IN E=46I=5FHANDLE Handle, > + IN CONST CHAR16 *ReportText > + ) > +=7B > + E=46I=5FSTATUS Status; > + > + Status =3D gBS->ConnectController ( > + Handle, // ControllerHandle > + NULL, // DriverImageHandle > + NULL, // RemainingDevicePath -- produce all children > + =46ALSE // Recursive > + ); > + DEBUG ((E=46I=5FERROR (Status) =3F DEBUG=5FERROR : DEBUG=5FVERBOSE, =22= %a: %s: %r=5Cn=22, > + =5F=5F=46UNCTION=5F=5F, ReportText, Status)); > +=7D > + > +/** > + This CALLBACK=5F=46UNCTION retrieves the E=46I=5FDEVICE=5FPATH=5FPROT= OCOL from the > + handle, and adds it to ConOut and ErrOut. > + > + =40param Handle The handle to retrieves. > + =40param ReportText A pointer to a string at the time of the error. > + > + =40retval VOID > +**/ > +VOID > +E=46IAPI > +AddOutput ( > + IN E=46I=5FHANDLE Handle, > + IN CONST CHAR16 *ReportText > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FDEVICE=5FPATH=5FPROTOCOL *DevicePath; > + > + DevicePath =3D DevicePath=46romHandle (Handle); > + if (DevicePath =3D=3D NULL) =7B > + DEBUG ((DEBUG=5FERROR, =22%a: %s: handle %p: device path not found=5C= n=22, > + =5F=5F=46UNCTION=5F=5F, ReportText, Handle)); > + return; > + =7D > + > + Status =3D EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, N= ULL); > + if (E=46I=5FERROR (Status)) =7B > + DEBUG ((DEBUG=5FERROR, =22%a: %s: adding to ConOut: %r=5Cn=22, =5F=5F= =46UNCTION=5F=5F, > + ReportText, Status)); > + return; > + =7D > + > + Status =3D EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, N= ULL); > + if (E=46I=5FERROR (Status)) =7B > + DEBUG ((DEBUG=5FERROR, =22%a: %s: adding to ErrOut: %r=5Cn=22, =5F=5F= =46UNCTION=5F=5F, > + ReportText, Status)); > + return; > + =7D > + > + DEBUG ((DEBUG=5FVERBOSE, =22%a: %s: added to ConOut and ErrOut=5Cn=22= , =5F=5F=46UNCTION=5F=5F, > + ReportText)); > +=7D > +/** > + Register the boot option. > + > + =40param =46ileGuid =46ile Guid. > + =40param Description Option descriptor. > + =40param Attributes Option Attributes. > + > + =40retval VOID > +**/ > +VOID > +PlatformRegister=46vBootOption ( > + IN E=46I=5FGUID *=46ileGuid, > + IN CHAR16 *Description, > + IN UINT32 Attributes > + ) > +=7B > + E=46I=5FSTATUS Status; > + INTN OptionIndex; > + E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTION NewOption; > + E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTION *BootOptions; > + UINTN BootOptionCount; > + MEDIA=5F=46W=5FVOL=5F=46ILEPATH=5FDEVICE=5FPATH =46ileNode; > + E=46I=5FLOADED=5FIMAGE=5FPROTOCOL *LoadedImage; > + E=46I=5FDEVICE=5FPATH=5FPROTOCOL *DevicePath; > + > + Status =3D gBS->HandleProtocol ( > + gImageHandle, > + &gEfiLoadedImageProtocolGuid, > + (VOID **) &LoadedImage > + ); > + ASSERT=5FE=46I=5FERROR (Status); > + > + EfiInitialize=46wVolDevicepathNode (&=46ileNode, =46ileGuid); > + DevicePath =3D DevicePath=46romHandle (LoadedImage->DeviceHandle); > + ASSERT (DevicePath =21=3D NULL); > + DevicePath =3D AppendDevicePathNode ( > + DevicePath, > + (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *) &=46ileNode > + ); > + ASSERT (DevicePath =21=3D NULL); > + > + Status =3D EfiBootManagerInitializeLoadOption ( > + &NewOption, > + LoadOptionNumberUnassigned, > + LoadOptionTypeBoot, > + Attributes, > + Description, > + DevicePath, > + NULL, > + 0 > + ); > + ASSERT=5FE=46I=5FERROR (Status); > + =46reePool (DevicePath); > + > + BootOptions =3D EfiBootManagerGetLoadOptions ( > + &BootOptionCount, LoadOptionTypeBoot > + ); > + > + OptionIndex =3D EfiBootManager=46indLoadOption ( > + &NewOption, BootOptions, BootOptionCount > + ); > + > + if (OptionIndex =3D=3D -1) =7B > + Status =3D EfiBootManagerAddLoadOptionVariable (&NewOption, MAX=5FUIN= TN); > + ASSERT=5FE=46I=5FERROR (Status); > + =7D > + EfiBootManager=46reeLoadOption (&NewOption); > + EfiBootManager=46reeLoadOptions (BootOptions, BootOptionCount); > +=7D > + > +/** > + Remove all MemoryMapped (...)/=46v=46ile (...) and =46v (...)/=46v=46= ile (...) boot options > + whose device paths do not resolve exactly to an =46v=46ile in the sys= tem. > + > + This removes any boot options that point to binaries built into the f= irmware > + and have become stale due to any of the following: > + - =46vMain's base address or size changed (historical), > + - =46vMain's =46vNameGuid changed, > + - the =46ILE=5FGUID of the pointed-to binary changed, > + - the referenced binary is no longer built into the firmware. > + > + EfiBootManager=46indLoadOption () used in PlatformRegister=46vBootOpt= ion () only > + avoids exact duplicates. > +**/ > +VOID > +RemoveStale=46v=46ileOptions ( > + VOID > + ) > +=7B > + E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTION *BootOptions; > + UINTN BootOptionCount; > + UINTN Index; > + > + BootOptions =3D EfiBootManagerGetLoadOptions (&BootOptionCount, > + LoadOptionTypeBoot); > + > + for (Index =3D 0; Index < BootOptionCount; ++Index) =7B > + E=46I=5FDEVICE=5FPATH=5FPROTOCOL *Node1, *Node2, *SearchNode; > + E=46I=5FSTATUS Status; > + E=46I=5FHANDLE =46vHandle; > + > + // > + // If the device path starts with neither MemoryMapped (...) nor =46v= (...), > + // then keep the boot option. > + // > + Node1 =3D BootOptions=5BIndex=5D.=46ilePath; > + if (=21(DevicePathType (Node1) =3D=3D HARDWARE=5FDEVICE=5FPATH > + && DevicePathSubType (Node1) =3D=3D HW=5FMEMMAP=5FDP) > + && =21(DevicePathType (Node1) =3D=3D MEDIA=5FDEVICE=5FPATH > + && DevicePathSubType (Node1) =3D=3D MEDIA=5FPIWG=5F=46W=5FVOL=5FDP)) > + =7B > + continue; > + =7D > + > + // > + // If the second device path node is not =46v=46ile (...), then keep = the boot > + // option. > + // > + Node2 =3D NextDevicePathNode (Node1); > + if ((DevicePathType (Node2) =21=3D MEDIA=5FDEVICE=5FPATH) > + =7C=7C (DevicePathSubType (Node2) =21=3D MEDIA=5FPIWG=5F=46W=5F=46ILE= =5FDP)) > + =7B > + continue; > + =7D > + > + // > + // Locate the =46irmware Volume2 protocol instance that is denoted by= the > + // boot option. If this lookup fails (i.e., the boot option reference= s a > + // firmware volume that doesn't exist), then we'll proceed to delete = the > + // boot option. > + // > + SearchNode =3D Node1; > + Status =3D gBS->LocateDevicePath (&gEfi=46irmwareVolume2ProtocolGuid,= > + &SearchNode, &=46vHandle); > + > + if (=21E=46I=5FERROR (Status)) =7B > + // > + // The firmware volume was found; now let's see if it contains the =46= v=46ile > + // identified by GUID. > + // > + E=46I=5F=46IRMWARE=5FVOLUME2=5FPROTOCOL *=46vProtocol; > + MEDIA=5F=46W=5FVOL=5F=46ILEPATH=5FDEVICE=5FPATH *=46v=46ileNode; > + UINTN BufferSize; > + E=46I=5F=46V=5F=46ILETYPE =46oundType; > + E=46I=5F=46V=5F=46ILE=5FATTRIBUTES =46ileAttributes; > + UINT32 AuthenticationStatus; > + > + Status =3D gBS->HandleProtocol (=46vHandle, &gEfi=46irmwareVolume2Pro= tocolGuid, > + (VOID **)&=46vProtocol); > + ASSERT=5FE=46I=5FERROR (Status); > + > + =46v=46ileNode =3D (MEDIA=5F=46W=5FVOL=5F=46ILEPATH=5FDEVICE=5FPATH *= )Node2; > + // > + // Buffer=3D=3DNULL means we request metadata only: BufferSize, =46ou= ndType, > + // =46ileAttributes. > + // > + Status =3D =46vProtocol->Read=46ile ( > + =46vProtocol, > + &=46v=46ileNode->=46v=46ileName, // NameGuid > + NULL, // Buffer > + &BufferSize, > + &=46oundType, > + &=46ileAttributes, > + &AuthenticationStatus > + ); > + if (=21E=46I=5FERROR (Status)) =7B > + // > + // The =46v=46ile was found. Keep the boot option. > + // > + continue; > + =7D > + =7D > + > + // > + // Delete the boot option. > + // > + Status =3D EfiBootManagerDeleteLoadOptionVariable ( > + BootOptions=5BIndex=5D.OptionNumber, LoadOptionTypeBoot); > + DEBUG=5FCODE ( > + CHAR16 *DevicePathString; > + > + DevicePathString =3D ConvertDevicePathToText (BootOptions=5BIndex=5D.= =46ilePath, > + =46ALSE, =46ALSE); > + DEBUG (( > + E=46I=5FERROR (Status) =3F E=46I=5FD=5FWARN : DEBUG=5FVERBOSE, > + =22%a: removing stale Boot=23%04x %s: %r=5Cn=22, > + =5F=5F=46UNCTION=5F=5F, > + (UINT32)BootOptions=5BIndex=5D.OptionNumber, > + DevicePathString =3D=3D NULL =3F L=22=22 : DevicePathStr= ing, > + Status > + )); > + if (DevicePathString =21=3D NULL) =7B > + =46reePool (DevicePathString); > + =7D > + ); > + =7D > + > + EfiBootManager=46reeLoadOptions (BootOptions, BootOptionCount); > +=7D > + > +/** > + Register the boot option And Keys. > + > + =40param VOID > + > + =40retval VOID > +**/ > +VOID > +PlatformRegisterOptionsAndKeys ( > + VOID > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FINPUT=5FKEY Enter; > + E=46I=5FINPUT=5FKEY =462; > + E=46I=5FINPUT=5FKEY Esc; > + E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTION BootOption; > + > + // > + // Register ENTER as CONTINUE key > + // > + Enter.ScanCode =3D SCAN=5FNULL; > + Enter.UnicodeChar =3D CHAR=5FCARRIAGE=5FRETURN; > + Status =3D EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);= > + ASSERT=5FE=46I=5FERROR (Status); > + > + // > + // Map =462 and ESC to Boot Manager Menu > + // > + =462.ScanCode =3D SCAN=5F=462; > + =462.UnicodeChar =3D CHAR=5FNULL; > + Esc.ScanCode =3D SCAN=5FESC; > + Esc.UnicodeChar =3D CHAR=5FNULL; > + Status =3D EfiBootManagerGetBootManagerMenu (&BootOption); > + ASSERT=5FE=46I=5FERROR (Status); > + Status =3D EfiBootManagerAddKeyOptionVariable ( > + NULL, (UINT16) BootOption.OptionNumber, 0, &=462, NULL > + ); > + ASSERT (Status =3D=3D E=46I=5FSUCCESS =7C=7C Status =3D=3D E=46I=5FAL= READY=5FSTARTED); > + Status =3D EfiBootManagerAddKeyOptionVariable ( > + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL > + ); > + ASSERT (Status =3D=3D E=46I=5FSUCCESS =7C=7C Status =3D=3D E=46I=5FAL= READY=5FSTARTED); > +=7D > + > +// > +// BDS Platform =46unctions > +// > +/** > + Do the platform init, can be customized by OEM/IBV > + Possible things that can be done in PlatformBootManagerBeforeConsole:= > + > Update console variable: 1. include hot-plug devices; > + > 2. Clear ConIn and add SOL for AMT > + > Register new Driver=23=23=23=23 or Boot=23=23=23=23 > + > Register new Key=23=23=23=23: e.g.: =4612 > + > Signal ReadyToLock event > + > Authentication action: 1. connect Auth devices; > + > 2. Identify auto logon user. > +**/ > +VOID > +E=46IAPI > +PlatformBootManagerBeforeConsole ( > + VOID > + ) > +=7B > + RETURN=5FSTATUS PcdStatus; > + > + // > + // Signal EndOfDxe PI Event > + // > + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); > + > + // > + // Dispatch deferred images after EndOfDxe event. > + // > + EfiBootManagerDispatchDeferredImages (); > + > + // > + // Locate the PCI root bridges and make the PCI bus driver connect ea= ch, > + // non-recursively. This will produce a number of child handles with = PciIo on > + // them. > + // > + =46ilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);= > + > + // > + // Signal the ACPI platform driver that it can download QEMU ACPI tab= les. > + // > + EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid); > + > + // > + // =46ind all display class PCI devices (using the handles from the p= revious > + // step), and connect them non-recursively. This should produce a num= ber of > + // child handles with GOPs on them. > + // > + =46ilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect); > + > + // > + // Now add the device path of all handles with GOP on them to ConOut = and > + // ErrOut. > + // > + =46ilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput)= ; > + > + // > + // Add the hardcoded short-form USB keyboard device path to ConIn. > + // > + EfiBootManagerUpdateConsoleVariable (ConIn, > + (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mUsbKeyboard, NULL); > + > + // > + // Add the hardcoded serial console device path to ConIn, ConOut, Err= Out. > + // > + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); > + EfiBootManagerUpdateConsoleVariable (ConIn, > + (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL); > + EfiBootManagerUpdateConsoleVariable (ConOut, > + (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL); > + EfiBootManagerUpdateConsoleVariable (ErrOut, > + (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL); > + > + // > + // Set the front page timeout from the QEMU configuration. > + // > + PcdStatus =3D PcdSet16S (PcdPlatformBootTimeOut, > + Get=46rontPageTimeout=46romQemu ()); > + ASSERT=5FRETURN=5FERROR (PcdStatus); > + > + // > + // Register platform-specific boot options and keyboard shortcuts. > + // > + PlatformRegisterOptionsAndKeys (); > +=7D > + > +/** > + Do the platform specific action after the console is ready > + Possible things that can be done in PlatformBootManagerAfterConsole: > + > Console post action: > + > Dynamically switch output mode from 100x31 to 80x25 for certain sen= arino > + > Signal console ready platform customized event > + > Run diagnostics like memory testing > + > Connect certain devices > + > Dispatch aditional option roms > + > Special boot: e.g.: USB boot, enter UI > +**/ > +VOID > +E=46IAPI > +PlatformBootManagerAfterConsole ( > + VOID > + ) > +=7B > + // > + // Show the splash screen. > + // > + BootLogoEnableLogo (); > + > + // > + // Connect the rest of the devices. > + // > + EfiBootManagerConnectAll (); > + > + // > + // Process QEMU's -kernel command line option. Note that the kernel b= ooted > + // this way should receive ACPI tables, which is why we connect all d= evices > + // first (see above) -- PCI enumeration blocks ACPI table installatio= n, if > + // there is a PCI host. > + // > + TryRunningQemuKernel (); > + > + // > + // Enumerate all possible boot options, then filter and reorder them = based on > + // the QEMU configuration. > + // > + EfiBootManagerRefreshAllBootOption (); > + > + // > + // Register UE=46I Shell > + // > + PlatformRegister=46vBootOption ( > + &gUefiShell=46ileGuid, L=22E=46I Internal Shell=22, LOAD=5FOPTION=5FA= CTIVE > + ); > + > + RemoveStale=46v=46ileOptions (); > + SetBootOrder=46romQemu (); > +=7D > + > +/** > + This function is called each second during the boot manager waits the= > + timeout. > + > + =40param TimeoutRemain The remaining timeout. > +**/ > +VOID > +E=46IAPI > +PlatformBootManagerWaitCallback ( > + IN UINT16 TimeoutRemain > + ) > +=7B > + E=46I=5FGRAPHICS=5FOUTPUT=5FBLT=5FPIXEL=5FUNION Black; > + E=46I=5FGRAPHICS=5FOUTPUT=5FBLT=5FPIXEL=5FUNION White; > + UINT16 Timeout; > + > + Timeout =3D PcdGet16 (PcdPlatformBootTimeOut); > + > + Black.Raw =3D 0x00000000; > + White.Raw =3D 0x00=46=46=46=46=46=46; > + > + BootLogoUpdateProgress ( > + White.Pixel, > + Black.Pixel, > + L=22Start boot option=22, > + White.Pixel, > + (Timeout - TimeoutRemain) * 100 / Timeout, > + 0 > + ); > +=7D > + > +/** > + The function is called when no boot option could be launched, > + including platform recovery options and options pointing to applicati= ons > + built into firmware volumes. > + > + If this function returns, BDS attempts to enter an infinite loop. > +**/ > +VOID > +E=46IAPI > +PlatformBootManagerUnableToBoot ( > + VOID > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FINPUT=5FKEY Key; > + E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTION BootManagerMenu; > + UINTN Index; > + > + // > + // BootManagerMenu doesn't contain the correct information when retur= n status > + // is E=46I=5FNOT=5F=46OUND. > + // > + Status =3D EfiBootManagerGetBootManagerMenu (&BootManagerMenu); > + if (E=46I=5FERROR (Status)) =7B > + return; > + =7D > + // > + // Normally BdsDxe does not print anything to the system console, but= this is > + // a last resort -- the end-user will likely not see any DEBUG messag= es > + // logged in this situation. > + // > + // AsciiPrint () will NULL-check gST->ConOut internally. We check gST= ->ConIn > + // here to see if it makes sense to request and wait for a keypress. > + // > + if (gST->ConIn =21=3D NULL) =7B > + AsciiPrint ( > + =22%a: No bootable option or device was found.=5Cn=22 > + =22%a: Press any key to enter the Boot Manager Menu.=5Cn=22, > + gEfiCallerBaseName, > + gEfiCallerBaseName > + ); > + Status =3D gBS->Wait=46orEvent (1, &gST->ConIn->Wait=46orKey, &Index)= ; > + ASSERT=5FE=46I=5FERROR (Status); > + ASSERT (Index =3D=3D 0); > + > + // > + // Drain any queued keys. > + // > + while (=21E=46I=5FERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key)= )) =7B > + // > + // just throw away Key > + // > + =7D > + =7D > + > + for (;;) =7B > + EfiBootManagerBoot (&BootManagerMenu); > + =7D > +=7D > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootMan= agerLib/PlatformBm.h b/Platform/Loongson/LoongArchQemuPkg/Library/Platfor= mBootManagerLib/PlatformBm.h > new file mode 100644 > index 0000000000..f20c78252f > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib= /PlatformBm.h > =40=40 -0,0 +1,112 =40=40 > +/** =40file > + Head file for BDS Platform specific code > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +=23ifndef PLAT=46ORM=5FBM=5FH=5F > +=23define PLAT=46ORM=5FBM=5FH=5F > + > +=23include > + > +=23define DP=5FNODE=5FLEN(Type) =7B (UINT8)sizeof (Type), (UINT8)(size= of (Type) >> 8) =7D > + > +=23define SERIAL=5FDXE=5F=46ILE=5FGUID =7B =5C > + 0xD3987D4B, 0x971A, 0x435=46, =5C > + =7B 0x8C, 0xA=46, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 =7D =5C > + =7D > + > +=23define ALIGN=5FUP(addr, align) =5C > + ((addr + (typeof (addr)) align - 1) & =7E((typeof (addr)) align - 1))= > + > +=23pragma pack (1) > +typedef struct =7B > + VENDOR=5FDEVICE=5FPATH SerialDxe; > + UART=5FDEVICE=5FPATH Uart; > + VENDOR=5FDE=46INED=5FDEVICE=5FPATH TermType; > + E=46I=5FDEVICE=5FPATH=5FPROTOCOL End; > +=7D PLAT=46ORM=5FSERIAL=5FCONSOLE; > +=23pragma pack () > + > +=23pragma pack (1) > +typedef struct =7B > + USB=5FCLASS=5FDEVICE=5FPATH Keyboard; > + E=46I=5FDEVICE=5FPATH=5FPROTOCOL End; > +=7D PLAT=46ORM=5FUSB=5FKEYBOARD; > +=23pragma pack () > + > +/** > + Check if the handle satisfies a particular condition. > + > + =40param=5Bin=5D Handle The handle to check. > + =40param=5Bin=5D ReportText A caller-allocated string passed in for r= eporting > + purposes. It must never be NULL. > + > + =40retval TRUE The condition is satisfied. > + =40retval =46ALSE Otherwise. This includes the case when the conditio= n could not > + be fully evaluated due to an error. > +**/ > +typedef > +BOOLEAN > +(E=46IAPI *=46ILTER=5F=46UNCTION) ( > + IN E=46I=5FHANDLE Handle, > + IN CONST CHAR16 *ReportText > + ); > + > +/** > + Process a handle. > + > + =40param=5Bin=5D Handle The handle to process. > + =40param=5Bin=5D ReportText A caller-allocated string passed in for r= eporting > + purposes. It must never be NULL. > +**/ > +typedef > +VOID > +(E=46IAPI *CALLBACK=5F=46UNCTION) ( > + IN E=46I=5FHANDLE Handle, > + IN CONST CHAR16 *ReportText > + ); > + > +/** > + * execute from kernel entry point. > + * > + * =40param=5Bin=5D Argc The count of args. > + * =40param=5Bin=5D Argv The pointer to args array. > + * =40param=5Bin=5D Bpi The pointer to bootparaminterface struct. > + * =40param=5Bin=5D Vec The fourth args for kernel. > + ***/ > +typedef > +VOID > +(E=46IAPI *E=46I=5FKERNEL=5FENTRY=5FPOINT) ( > + IN UINTN Argc, > + IN VOID *Argv, > + IN VOID *Bpi, > + IN VOID *Vec > + ); > + > +/** > + Download the kernel, the initial ramdisk, and the kernel command line= from > + QEMU's fw=5Fcfg. Construct a minimal Simple=46ileSystem that contains= the two > + image files, and load and start the kernel from it. > + > + The kernel will be instructed via its command line to load the initrd= from > + the same Simple =46ileSystem. > + > + =40retval E=46I=5FNOT=5F=46OUND Kernel image was not found. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES Memory allocation failed. > + =40retval E=46I=5FPROTOCOL=5FERROR Unterminated kernel command line. > + > + =40return Error codes from any of the underlying > + functions. On success, the function doesn't > + return. > +**/ > +E=46I=5FSTATUS > +E=46IAPI > +TryRunningQemuKernel ( > + VOID > + ); > + > +=23endif // PLAT=46ORM=5FBM=5FH=5F > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootMan= agerLib/PlatformBootManagerLib.inf b/Platform/Loongson/LoongArchQemuPkg/L= ibrary/PlatformBootManagerLib/PlatformBootManagerLib.inf > new file mode 100644 > index 0000000000..0ea6fea5c5 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib= /PlatformBootManagerLib.inf > =40=40 -0,0 +1,75 =40=40 > +=23=23 =40file > +=23 Implementation for PlatformBootManagerLib library class interfaces= . > +=23 > +=23 Copyright (c) 2022 Loongson Technology Corporation Limited. All ri= ghts reserved.
> +=23 > +=23 SPDX-License-Identifier: BSD-2-Clause-Patent > +=23 > +=23=23 > + > +=5BDefines=5D > + IN=46=5FVERSION =3D 0x00010005 > + BASE=5FNAME =3D PlatformBootManagerLib > + =46ILE=5FGUID =3D 469184E8-=46ADA-41E4-8823-012CA19B40D4 > + MODULE=5FTYPE =3D DXE=5FDRIVER > + VERSION=5FSTRING =3D 1.0 > + LIBRARY=5FCLASS =3D PlatformBootManagerLib=7CDXE=5FDRIVER > + > +=23 > +=23 VALID=5FARCHITECTURES =3D LOONGARCH64 > +=23 > + > +=5BSources=5D > + PlatformBm.c > + QemuKernel.c > + > +=5BPackages=5D > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + ShellPkg/ShellPkg.dec > + > +=5BLibraryClasses=5D > + BaseLib > + BaseMemoryLib > + BootLogoLib > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + PcdLib > + PrintLib > + QemuBootOrderLib > + QemuLoadImageLib > + Qemu=46wCfgLib > + UefiBootManagerLib > + UefiBootServicesTableLib > + UefiLib > + UefiRuntimeServicesTableLib > + > +=5B=46ixedPcd=5D > + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate > + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits > + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity > + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits > + > +=5BPcd=5D > + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut > + > +=5BGuids=5D > + gEfi=46ileInfoGuid > + gEfi=46ileSystemInfoGuid > + gEfi=46ileSystemVolumeLabelInfoIdGuid > + gEfiEndOfDxeEventGroupGuid > + gRootBridgesConnectedEventGroupGuid > + gUefiShell=46ileGuid > + gEfiLoongsonBootparamsTableGuid =23=23 SOMETIMES=5FPRODUCES =23=23 Sy= stemTable > + gEfiTtyTermGuid > + > +=5BProtocols=5D > + gEfiDevicePathProtocolGuid > + gEfi=46irmwareVolume2ProtocolGuid > + gEfiGraphicsOutputProtocolGuid > + gEfiLoadedImageProtocolGuid > + gEfiPciRootBridgeIoProtocolGuid > + gEfiSimple=46ileSystemProtocolGuid > diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootMan= agerLib/QemuKernel.c b/Platform/Loongson/LoongArchQemuPkg/Library/Platfor= mBootManagerLib/QemuKernel.c > new file mode 100644 > index 0000000000..386003a8d7 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib= /QemuKernel.c > =40=40 -0,0 +1,81 =40=40 > +/** =40file > + Try to run Linux kernel. > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All right= s reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + =40par Glossary: > + - mem - Memory > + - Bpi - Boot Parameter Interface > + - =46wCfg - =46irmWare Configure > +**/ > + > +=23include > +=23include > + > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > +=23include > + > +/** > + Download the kernel, the initial ramdisk, and the kernel command line= from > + QEMU's fw=5Fcfg. Construct a minimal Simple=46ileSystem that contains= the two > + image files, and load and start the kernel from it. > + > + The kernel will be instructed via its command line to load the initrd= from > + the same Simple =46ileSystem. > + > + =40retval E=46I=5FNOT=5F=46OUND Kernel image was not found. > + =40retval E=46I=5FOUT=5FO=46=5FRESOURCES Memory allocation failed. > + =40retval E=46I=5FPROTOCOL=5FERROR Unterminated kernel command line. > + > + =40return Error codes from any of the underlying > + functions. On success, the function doesn't > + return. > +**/ > +E=46I=5FSTATUS > +TryRunningQemuKernel ( > + VOID > + ) > +=7B > + E=46I=5FSTATUS Status; > + E=46I=5FHANDLE KernelImageHandle; > + > + Status =3D QemuLoadKernelImage (&KernelImageHandle); > + if (E=46I=5FERROR (Status)) =7B > + return Status; > + =7D > + > + // > + // Signal the E=46I=5FEVENT=5FGROUP=5FREADY=5FTO=5FBOOT event. > + // > + EfiSignalEventReadyToBoot (); > + > + REPORT=5FSTATUS=5FCODE ( > + E=46I=5FPROGRESS=5FCODE, > + (E=46I=5FSO=46TWARE=5FDXE=5FBS=5FDRIVER =7C E=46I=5FSW=5FDXE=5FBS=5FP= C=5FREADY=5FTO=5FBOOT=5FEVENT) > + ); > + > + // > + // Start the image. > + // > + Status =3D QemuStartKernelImage (&KernelImageHandle); > + if (E=46I=5FERROR (Status)) =7B > + DEBUG (( > + DEBUG=5FERROR, > + =22%a: QemuStartKernelImage(): %r=5Cn=22, > + =5F=5F=46UNCTION=5F=5F, > + Status > + )); > + =7D > + > + QemuUnloadKernelImage (KernelImageHandle); > + > + return Status; > +=7D > -- > 2.31.1 --636e1a8a_189805c2_1e57b Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline
Reviewed-by: Chao Li  <lichao=40loongson.cn>


Thanks,
Chao
--------

On 11=E6=9C=88 11 2= 022, at 5:12 =E4=B8=8B=E5=8D=88, xianglai li <lixianglai=40loongson.cn= > wrote:
The Library provides Boot Manager = interfaces.



RE=46: https://bugzilla.tianocore.org/s= how=5Fbug.cgi=3Fid=3D4054



Cc: Bibo Mao <maobibo=40= loongson.cn>

Cc: Chao Li <lichao=40loongson.cn>
Cc: Leif Lindholm <quic=5Fllindhol=40quicinc.com>
=
Cc: Liming Gao <gaoliming=40byosoft.com.cn>

= Cc: Michael D Kinney <michael.d.kinney=40intel.com>

S= igned-off-by: xianglai li <lixianglai=40loongson.cn>

= ---

.../PlatformBootManagerLib/PlatformBm.c =7C 742 +++++++= +++++++++++

.../PlatformBootManagerLib/PlatformBm.h =7C 112= +++

.../PlatformBootManagerLib.inf =7C 75 ++

.../PlatformBootManagerLib/QemuKernel.c =7C 81 ++

4 files = changed, 1010 insertions(+)

create mode 100644 Platform/Loo= ngson/LoongArchQemuPkg/Library/PlatformBootManagerLib/PlatformBm.c
<= br>
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Library/Pla= tformBootManagerLib/PlatformBm.h

create mode 100644 Platfor= m/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/PlatformBootMa= nagerLib.inf

create mode 100644 Platform/Loongson/LoongArch= QemuPkg/Library/PlatformBootManagerLib/QemuKernel.c



diff --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootMana= gerLib/PlatformBm.c b/Platform/Loongson/LoongArchQemuPkg/Library/Platform= BootManagerLib/PlatformBm.c

new file mode 100644

<= div>index 0000000000..eb7f4241f0
--- /dev/null

+++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib= /PlatformBm.c
=40=40 -0,0 +1,742 =40=40

+/** = =40file

+ Implementation for PlatformBootManagerLib library= class interfaces.

+

+ Copyright (c) 2022 Loo= ngson Technology Corporation Limited. All rights reserved.<BR>
+

+ SPDX-License-Identifier: BSD-2-Clause-Patent<= /div>
+

+**/

+

+=23incl= ude <IndustryStandard/Pci22.h>

+=23include <Librar= y/BootLogoLib.h>

+=23include <Library/PcdLib.h>
+=23include <Library/QemuBootOrderLib.h>

= +=23include <Library/UefiBootManagerLib.h>

+=23includ= e <Protocol/=46irmwareVolume2.h>

+=23include <Prot= ocol/LoadedImage.h>

+=23include <Protocol/PciIo.h>=

+=23include <Library/UefiBootServicesTableLib.h>
+=23include <Library/DebugLib.h>

+=23inclu= de <Library/MemoryAllocationLib.h>

+=23include <Li= brary/UefiLib.h>

+=23include <Library/BaseMemoryLib.h= >

+=23include =22PlatformBm.h=22

+
+STATIC PLAT=46ORM=5FSERIAL=5FCONSOLE mSerialConsole =3D =7B
=
+ //

+ // VENDOR=5FDEVICE=5FPATH SerialDxe
+ //

+ =7B

+ =7B HARDWARE=5FDEVICE=5FP= ATH, HW=5FVENDOR=5FDP, DP=5FNODE=5FLEN (VENDOR=5FDEVICE=5FPATH) =7D,
+ SERIAL=5FDXE=5F=46ILE=5FGUID

+ =7D,

+

+ //

+ // UART=5FDEVICE=5FPATH Uart
+ //

+ =7B

+ =7B MESSAGING=5FDEVICE= =5FPATH, MSG=5FUART=5FDP, DP=5FNODE=5FLEN (UART=5FDEVICE=5FPATH) =7D,
+ 0, // Reserved

+ =46ixedPcdGet64 (PcdUartDefau= ltBaudRate), // BaudRate

+ =46ixedPcdGet8 (PcdUartDefaultDa= taBits), // DataBits

+ =46ixedPcdGet8 (PcdUartDefaultParity= ), // Parity

+ =46ixedPcdGet8 (PcdUartDefaultStopBits) // S= topBits

+ =7D,

+

+ //

=
+ // VENDOR=5FDE=46INED=5FDEVICE=5FPATH TermType

+ //<= /div>
+ =7B

+ =7B

+ MESSAGING=5FDEVIC= E=5FPATH, MSG=5FVENDOR=5FDP,

+ DP=5FNODE=5FLEN (VENDOR=5FDE= =46INED=5FDEVICE=5FPATH)

+ =7D

+ //

=
+ // Guid to be filled in dynamically

+ //

+ =7D,

+

+ //

+ // E=46I=5FD= EVICE=5FPATH=5FPROTOCOL End

+ //

+ =7B
<= br>
+ END=5FDEVICE=5FPATH=5FTYPE, END=5FENTIRE=5FDEVICE=5FPATH=5FSUBT= YPE,

+ DP=5FNODE=5FLEN (E=46I=5FDEVICE=5FPATH=5FPROTOCOL)
+ =7D

+=7D;

+

+STA= TIC PLAT=46ORM=5FUSB=5FKEYBOARD mUsbKeyboard =3D =7B

+ //
+ // USB=5FCLASS=5FDEVICE=5FPATH Keyboard

+ //=

+ =7B

+ =7B

+ MESSAGING=5FDEVI= CE=5FPATH, MSG=5FUSB=5FCLASS=5FDP,

+ DP=5FNODE=5FLEN (USB=5F= CLASS=5FDEVICE=5FPATH)

+ =7D,

+ 0x=46=46=46=46= , // VendorId: any

+ 0x=46=46=46=46, // ProductId: any
+ 3, // DeviceClass: HID

+ 1, // DeviceSubClass: = boot

+ 1 // DeviceProtocol: keyboard

+ =7D,
+

+ //

+ // E=46I=5FDEVICE=5FPAT= H=5FPROTOCOL End

+ //

+ =7B

+ E= ND=5FDEVICE=5FPATH=5FTYPE, END=5FENTIRE=5FDEVICE=5FPATH=5FSUBTYPE,
<= br>
+ DP=5FNODE=5FLEN (E=46I=5FDEVICE=5FPATH=5FPROTOCOL)

+ =7D

+=7D;

+

+/**

<= div>+ Locate all handles that carry the specified protocol, filter them w= ith a

+ callback function, and pass each handle that passes= the filter to another

+ callback.

+
+ =40param=5Bin=5D ProtocolGuid The protocol to look for.

=
+

+ =40param=5Bin=5D =46ilter The filter function to p= ass each handle to. If this

+ parameter is NULL, then all h= andles are processed.

+

+ =40param=5Bin=5D Pr= ocess The callback function to pass each handle to that

+ c= lears the filter.

+**/

+VOID

+=46= ilterAndProcess (

+ IN E=46I=5FGUID *ProtocolGuid,
+ IN =46ILTER=5F=46UNCTION =46ilter OPTIONAL,

+ IN CA= LLBACK=5F=46UNCTION Process

+ )

+=7B
+ E=46I=5FSTATUS Status;

+ E=46I=5FHANDLE *Handles;
+ UINTN NoHandles;

+ UINTN Idx;

= +

+ Status =3D gBS->LocateHandleBuffer (ByProtocol, Prot= ocolGuid,

+ NULL /* SearchKey */, &NoHandles, &Hand= les);

+ if (E=46I=5FERROR (Status)) =7B

+ //<= /div>
+ // This is not an error, just an informative condition.
+ //

+ DEBUG ((DEBUG=5FVERBOSE, =22%a: %g: %r=5C= n=22, =5F=5F=46UNCTION=5F=5F, ProtocolGuid,

+ Status));
+ return;

+ =7D

+

+ = ASSERT (NoHandles > 0);

+ for (Idx =3D 0; Idx < NoHan= dles; ++Idx) =7B

+ CHAR16 *DevicePathText;

+ = STATIC CHAR16 =46allback=5B=5D =3D L=22<device path unavailable>=22= ;

+

+ //

+ // The ConvertDevice= PathToText () function handles NULL input transparently.

+ = //

+ DevicePathText =3D ConvertDevicePathToText (

=
+ DevicePath=46romHandle (Handles=5BIdx=5D),

+ =46ALSE= , // DisplayOnly

+ =46ALSE // AllowShortcuts

= + );

+ if (DevicePathText =3D=3D NULL) =7B

+ = DevicePathText =3D =46allback;

+ =7D

+
<= br>
+ if ((=46ilter =3D=3D NULL)

+ =7C=7C (=46ilter (Ha= ndles=5BIdx=5D, DevicePathText)))

+ =7B

+ Pro= cess (Handles=5BIdx=5D, DevicePathText);

+ =7D

+

+ if (DevicePathText =21=3D =46allback) =7B

+ =46reePool (DevicePathText);

+ =7D

+ =7D=

+ gBS->=46reePool (Handles);

+=7D
+

+/**

+ This =46ILTER=5F=46UNCTION ch= ecks if a handle corresponds to a PCI display device.

+
+ =40param Handle The handle to check

+ =40param= ReportText A pointer to a string at the time of the error.

+

+ =40retval TURE THe handle corresponds to a PCI display= device.

+ =40retval =46ALSE THe handle does not correspond= s to a PCI display device.

+**/

+BOOLEAN
+E=46IAPI

+IsPciDisplay (

+ IN E=46= I=5FHANDLE Handle,

+ IN CONST CHAR16 *ReportText

<= div>+ )

+=7B

+ E=46I=5FSTATUS Status;
+ E=46I=5FPCI=5FIO=5FPROTOCOL *PciIo;

+ PCI=5FTYPE00= Pci;

+

+ Status =3D gBS->HandleProtocol (= Handle, &gEfiPciIoProtocolGuid,

+ (VOID**)&PciIo);<= /div>
+ if (E=46I=5FERROR (Status)) =7B

+ //
<= br>
+ // This is not an error worth reporting.

+ //
+ return =46ALSE;

+ =7D

+
+ Status =3D PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* O= ffset */,

+ sizeof Pci / sizeof (UINT32), &Pci);
<= br>
+ if (E=46I=5FERROR (Status)) =7B

+ DEBUG ((DEBUG=5F= ERROR, =22%a: %s: %r=5Cn=22, =5F=5F=46UNCTION=5F=5F, ReportText, Status))= ;

+ return =46ALSE;

+ =7D

+
+ return IS=5FPCI=5FDISPLAY (&Pci);

+=7D
+

+/**

+ This CALLBACK=5F=46UNCTIO= N attempts to connect a handle non-recursively, asking

+ th= e matching driver to produce all first-level child handles.

+

+ =40param Handle The handle to connect.

+= =40param ReportText A pointer to a string at the time of the error.
+

+ =40retval VOID

+**/

+VOID

+E=46IAPI

+Connect (

+= IN E=46I=5FHANDLE Handle,

+ IN CONST CHAR16 *ReportText
+ )

+=7B

+ E=46I=5FSTATUS Status;=

+

+ Status =3D gBS->ConnectController (
+ Handle, // ControllerHandle

+ NULL, // Drive= rImageHandle

+ NULL, // RemainingDevicePath -- produce all = children

+ =46ALSE // Recursive

+ );
+ DEBUG ((E=46I=5FERROR (Status) =3F DEBUG=5FERROR : DEBUG=5FVERBOS= E, =22%a: %s: %r=5Cn=22,

+ =5F=5F=46UNCTION=5F=5F, ReportTe= xt, Status));

+=7D

+

+/**
=
+ This CALLBACK=5F=46UNCTION retrieves the E=46I=5FDEVICE=5FPATH= =5FPROTOCOL from the

+ handle, and adds it to ConOut and Er= rOut.

+

+ =40param Handle The handle to retri= eves.

+ =40param ReportText A pointer to a string at the ti= me of the error.

+

+ =40retval VOID

=
+**/

+VOID

+E=46IAPI

+AddO= utput (

+ IN E=46I=5FHANDLE Handle,

+ IN CONS= T CHAR16 *ReportText

+ )

+=7B

+= E=46I=5FSTATUS Status;

+ E=46I=5FDEVICE=5FPATH=5FPROTOCOL = *DevicePath;

+

+ DevicePath =3D DevicePath=46= romHandle (Handle);

+ if (DevicePath =3D=3D NULL) =7B
=
+ DEBUG ((DEBUG=5FERROR, =22%a: %s: handle %p: device path not f= ound=5Cn=22,

+ =5F=5F=46UNCTION=5F=5F, ReportText, Handle))= ;

+ return;

+ =7D

+

+ Status =3D EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, = NULL);

+ if (E=46I=5FERROR (Status)) =7B

+ DE= BUG ((DEBUG=5FERROR, =22%a: %s: adding to ConOut: %r=5Cn=22, =5F=5F=46UNC= TION=5F=5F,

+ ReportText, Status));

+ return;=

+ =7D

+

+ Status =3D EfiBootMa= nagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);

+ if= (E=46I=5FERROR (Status)) =7B

+ DEBUG ((DEBUG=5FERROR, =22%= a: %s: adding to ErrOut: %r=5Cn=22, =5F=5F=46UNCTION=5F=5F,

+ ReportText, Status));

+ return;

+ =7D
+

+ DEBUG ((DEBUG=5FVERBOSE, =22%a: %s: added to = ConOut and ErrOut=5Cn=22, =5F=5F=46UNCTION=5F=5F,

+ ReportT= ext));

+=7D

+/**

+ Register the= boot option.

+

+ =40param =46ileGuid =46ile = Guid.

+ =40param Description Option descriptor.

+ =40param Attributes Option Attributes.

+

+ =40retval VOID

+**/

+VOID

+P= latformRegister=46vBootOption (

+ IN E=46I=5FGUID *=46ileGu= id,

+ IN CHAR16 *Description,

+ IN UINT32 Att= ributes

+ )

+=7B

+ E=46I=5FSTAT= US Status;

+ INTN OptionIndex;

+ E=46I=5FBOOT= =5FMANAGER=5FLOAD=5FOPTION NewOption;

+ E=46I=5FBOOT=5FMANA= GER=5FLOAD=5FOPTION *BootOptions;

+ UINTN BootOptionCount;<= /div>
+ MEDIA=5F=46W=5FVOL=5F=46ILEPATH=5FDEVICE=5FPATH =46ileNod= e;

+ E=46I=5FLOADED=5FIMAGE=5FPROTOCOL *LoadedImage;
<= br>
+ E=46I=5FDEVICE=5FPATH=5FPROTOCOL *DevicePath;

+
+ Status =3D gBS->HandleProtocol (

+ gImage= Handle,

+ &gEfiLoadedImageProtocolGuid,

+= (VOID **) &LoadedImage

+ );

+ ASSERT=5FE= =46I=5FERROR (Status);

+

+ EfiInitialize=46wV= olDevicepathNode (&=46ileNode, =46ileGuid);

+ DevicePat= h =3D DevicePath=46romHandle (LoadedImage->DeviceHandle);

+ ASSERT (DevicePath =21=3D NULL);

+ DevicePath =3D Appen= dDevicePathNode (

+ DevicePath,

+ (E=46I=5FDE= VICE=5FPATH=5FPROTOCOL *) &=46ileNode

+ );

+ ASSERT (DevicePath =21=3D NULL);

+

+ Stat= us =3D EfiBootManagerInitializeLoadOption (

+ &NewOptio= n,

+ LoadOptionNumberUnassigned,

+ LoadOption= TypeBoot,

+ Attributes,

+ Description,
<= br>
+ DevicePath,

+ NULL,

+ 0

+ );

+ ASSERT=5FE=46I=5FERROR (Status);

+ = =46reePool (DevicePath);

+

+ BootOptions =3D = EfiBootManagerGetLoadOptions (

+ &BootOptionCount, Load= OptionTypeBoot

+ );

+

+ OptionI= ndex =3D EfiBootManager=46indLoadOption (

+ &NewOption,= BootOptions, BootOptionCount

+ );

+
+ if (OptionIndex =3D=3D -1) =7B

+ Status =3D EfiBoot= ManagerAddLoadOptionVariable (&NewOption, MAX=5FUINTN);

+ ASSERT=5FE=46I=5FERROR (Status);

+ =7D

+ E= fiBootManager=46reeLoadOption (&NewOption);

+ EfiBootMa= nager=46reeLoadOptions (BootOptions, BootOptionCount);

+=7D=

+

+/**

+ Remove all MemoryMapp= ed (...)/=46v=46ile (...) and =46v (...)/=46v=46ile (...) boot options
+ whose device paths do not resolve exactly to an =46v=46ile = in the system.

+

+ This removes any boot opti= ons that point to binaries built into the firmware

+ and ha= ve become stale due to any of the following:

+ - =46vMain's= base address or size changed (historical),

+ - =46vMain's = =46vNameGuid changed,

+ - the =46ILE=5FGUID of the pointed-= to binary changed,

+ - the referenced binary is no longer b= uilt into the firmware.

+

+ EfiBootManager=46= indLoadOption () used in PlatformRegister=46vBootOption () only

=
+ avoids exact duplicates.

+**/

+VOID
+RemoveStale=46v=46ileOptions (

+ VOID
+ )

+=7B

+ E=46I=5FBOOT=5FMANAGER=5FLOA= D=5FOPTION *BootOptions;

+ UINTN BootOptionCount;

=
+ UINTN Index;

+

+ BootOptions =3D EfiBo= otManagerGetLoadOptions (&BootOptionCount,

+ LoadOption= TypeBoot);

+

+ for (Index =3D 0; Index < B= ootOptionCount; ++Index) =7B

+ E=46I=5FDEVICE=5FPATH=5FPROT= OCOL *Node1, *Node2, *SearchNode;

+ E=46I=5FSTATUS Status;<= /div>
+ E=46I=5FHANDLE =46vHandle;

+

= + //

+ // If the device path starts with neither MemoryMapp= ed (...) nor =46v (...),

+ // then keep the boot option.
+ //

+ Node1 =3D BootOptions=5BIndex=5D.=46ileP= ath;

+ if (=21(DevicePathType (Node1) =3D=3D HARDWARE=5FDEV= ICE=5FPATH

+ && DevicePathSubType (Node1) =3D=3D HW= =5FMEMMAP=5FDP)

+ && =21(DevicePathType (Node1) =3D= =3D MEDIA=5FDEVICE=5FPATH

+ && DevicePathSubType (N= ode1) =3D=3D MEDIA=5FPIWG=5F=46W=5FVOL=5FDP))

+ =7B
+ continue;

+ =7D

+

+ //=

+ // If the second device path node is not =46v=46ile (...= ), then keep the boot

+ // option.

+ //
=
+ Node2 =3D NextDevicePathNode (Node1);

+ if ((Dev= icePathType (Node2) =21=3D MEDIA=5FDEVICE=5FPATH)

+ =7C=7C = (DevicePathSubType (Node2) =21=3D MEDIA=5FPIWG=5F=46W=5F=46ILE=5FDP))
+ =7B

+ continue;

+ =7D

<= div>+

+ //

+ // Locate the =46irmware Volume2= protocol instance that is denoted by the

+ // boot option.= If this lookup fails (i.e., the boot option references a

+= // firmware volume that doesn't exist), then we'll proceed to delete the=

+ // boot option.

+ //

+ Searc= hNode =3D Node1;

+ Status =3D gBS->LocateDevicePath (&am= p;gEfi=46irmwareVolume2ProtocolGuid,

+ &SearchNode, &am= p;=46vHandle);

+

+ if (=21E=46I=5FERROR (Stat= us)) =7B

+ //

+ // The firmware volume was fo= und; now let's see if it contains the =46v=46ile

+ // ident= ified by GUID.

+ //

+ E=46I=5F=46IRMWARE=5FVO= LUME2=5FPROTOCOL *=46vProtocol;

+ MEDIA=5F=46W=5FVOL=5F=46I= LEPATH=5FDEVICE=5FPATH *=46v=46ileNode;

+ UINTN BufferSize;=

+ E=46I=5F=46V=5F=46ILETYPE =46oundType;

+ E= =46I=5F=46V=5F=46ILE=5FATTRIBUTES =46ileAttributes;

+ UINT3= 2 AuthenticationStatus;

+

+ Status =3D gBS-&g= t;HandleProtocol (=46vHandle, &gEfi=46irmwareVolume2ProtocolGuid,
+ (VOID **)&=46vProtocol);

+ ASSERT=5FE=46I=5F= ERROR (Status);

+

+ =46v=46ileNode =3D (MEDIA= =5F=46W=5FVOL=5F=46ILEPATH=5FDEVICE=5FPATH *)Node2;

+ //
+ // Buffer=3D=3DNULL means we request metadata only: BufferS= ize, =46oundType,

+ // =46ileAttributes.

+ //=

+ Status =3D =46vProtocol->Read=46ile (

+= =46vProtocol,

+ &=46v=46ileNode->=46v=46ileName, //= NameGuid

+ NULL, // Buffer

+ &BufferSize= ,

+ &=46oundType,

+ &=46ileAttributes= ,

+ &AuthenticationStatus

+ );

<= div>+ if (=21E=46I=5FERROR (Status)) =7B

+ //

+ // The =46v=46ile was found. Keep the boot option.

+ //<= /div>
+ continue;

+ =7D

+ =7D
+

+ //

+ // Delete the boot option.
+ //

+ Status =3D EfiBootManagerDeleteLoadOptio= nVariable (

+ BootOptions=5BIndex=5D.OptionNumber, LoadOpti= onTypeBoot);

+ DEBUG=5FCODE (

+ CHAR16 *Devic= ePathString;

+

+ DevicePathString =3D Convert= DevicePathToText (BootOptions=5BIndex=5D.=46ilePath,

+ =46A= LSE, =46ALSE);

+ DEBUG ((

+ E=46I=5FERROR (St= atus) =3F E=46I=5FD=5FWARN : DEBUG=5FVERBOSE,

+ =22%a: remo= ving stale Boot=23%04x %s: %r=5Cn=22,

+ =5F=5F=46UNCTION=5F= =5F,

+ (UINT32)BootOptions=5BIndex=5D.OptionNumber,
+ DevicePathString =3D=3D NULL =3F L=22<unavailable>=22 : De= vicePathString,

+ Status

+ ));

= + if (DevicePathString =21=3D NULL) =7B

+ =46reePool (Devic= ePathString);

+ =7D

+ );

+ =7D<= /div>
+

+ EfiBootManager=46reeLoadOptions (BootOpti= ons, BootOptionCount);

+=7D

+

+= /**

+ Register the boot option And Keys.

+
+ =40param VOID

+

+ =40retval VOI= D

+**/

+VOID

+PlatformRegisterO= ptionsAndKeys (

+ VOID

+ )

+=7B=

+ E=46I=5FSTATUS Status;

+ E=46I=5FINPUT=5FK= EY Enter;

+ E=46I=5FINPUT=5FKEY =462;

+ E=46I= =5FINPUT=5FKEY Esc;

+ E=46I=5FBOOT=5FMANAGER=5FLOAD=5FOPTIO= N BootOption;

+

+ //

+ // Regis= ter ENTER as CONTINUE key

+ //

+ Enter.ScanCo= de =3D SCAN=5FNULL;

+ Enter.UnicodeChar =3D CHAR=5FCARRIAGE= =5FRETURN;

+ Status =3D EfiBootManagerRegisterContinueKeyOp= tion (0, &Enter, NULL);

+ ASSERT=5FE=46I=5FERROR (Statu= s);

+

+ //

+ // Map =462 and ES= C to Boot Manager Menu

+ //

+ =462.ScanCode =3D= SCAN=5F=462;

+ =462.UnicodeChar =3D CHAR=5FNULL;

=
+ Esc.ScanCode =3D SCAN=5FESC;

+ Esc.UnicodeChar =3D C= HAR=5FNULL;

+ Status =3D EfiBootManagerGetBootManagerMenu (= &BootOption);

+ ASSERT=5FE=46I=5FERROR (Status);
<= br>
+ Status =3D EfiBootManagerAddKeyOptionVariable (

+= NULL, (UINT16) BootOption.OptionNumber, 0, &=462, NULL

+ );

+ ASSERT (Status =3D=3D E=46I=5FSUCCESS =7C=7C Status= =3D=3D E=46I=5FALREADY=5FSTARTED);

+ Status =3D EfiBootMan= agerAddKeyOptionVariable (

+ NULL, (UINT16) BootOption.Opti= onNumber, 0, &Esc, NULL

+ );

+ ASSERT (St= atus =3D=3D E=46I=5FSUCCESS =7C=7C Status =3D=3D E=46I=5FALREADY=5FSTARTE= D);

+=7D

+

+//

+/= / BDS Platform =46unctions

+//

+/**

=
+ Do the platform init, can be customized by OEM/IBV

+= Possible things that can be done in PlatformBootManagerBeforeConsole:
+ > Update console variable: 1. include hot-plug devices;<= /div>
+ > 2. Clear ConIn and add SOL for AMT

+ &= gt; Register new Driver=23=23=23=23 or Boot=23=23=23=23

+ &= gt; Register new Key=23=23=23=23: e.g.: =4612

+ > Signal= ReadyToLock event

+ > Authentication action: 1. connect= Auth devices;

+ > 2. Identify auto logon user.
+**/

+VOID

+E=46IAPI

+Pla= tformBootManagerBeforeConsole (

+ VOID

+ )
+=7B

+ RETURN=5FSTATUS PcdStatus;

+

+ //

+ // Signal EndOfDxe PI Event
+ //

+ EfiEventGroupSignal (&gEfiEndOfDxeEventGr= oupGuid);

+

+ //

+ // Dispatch = deferred images after EndOfDxe event.

+ //

+ = EfiBootManagerDispatchDeferredImages ();

+

+ = //

+ // Locate the PCI root bridges and make the PCI bus dr= iver connect each,

+ // non-recursively. This will produce = a number of child handles with PciIo on

+ // them.
+ //

+ =46ilterAndProcess (&gEfiPciRootBridgeIoPr= otocolGuid, NULL, Connect);

+

+ //

<= div>+ // Signal the ACPI platform driver that it can download QEMU ACPI t= ables.

+ //

+ EfiEventGroupSignal (&gRoot= BridgesConnectedEventGroupGuid);

+

+ //
=
+ // =46ind all display class PCI devices (using the handles fro= m the previous

+ // step), and connect them non-recursively= . This should produce a number of

+ // child handles with G= OPs on them.

+ //

+ =46ilterAndProcess (&= gEfiPciIoProtocolGuid, IsPciDisplay, Connect);

+

<= div>+ //

+ // Now add the device path of all handles with G= OP on them to ConOut and

+ // ErrOut.

+ //
+ =46ilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NU= LL, AddOutput);

+

+ //

+ // Add= the hardcoded short-form USB keyboard device path to ConIn.

+ //

+ EfiBootManagerUpdateConsoleVariable (ConIn,
<= br>
+ (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mUsbKeyboard, NULL);
+

+ //

+ // Add the hardcoded se= rial console device path to ConIn, ConOut, ErrOut.

+ //
+ CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTer= mGuid);

+ EfiBootManagerUpdateConsoleVariable (ConIn,
=
+ (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL)= ;

+ EfiBootManagerUpdateConsoleVariable (ConOut,

<= div>+ (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut,

+= (E=46I=5FDEVICE=5FPATH=5FPROTOCOL *)&mSerialConsole, NULL);
+

+ //

+ // Set the front page timeout = from the QEMU configuration.

+ //

+ PcdStatus= =3D PcdSet16S (PcdPlatformBootTimeOut,

+ Get=46rontPageTim= eout=46romQemu ());

+ ASSERT=5FRETURN=5FERROR (PcdStatus);<= /div>
+

+ //

+ // Register platform-s= pecific boot options and keyboard shortcuts.

+ //

=
+ PlatformRegisterOptionsAndKeys ();

+=7D

+

+/**

+ Do the platform specific action af= ter the console is ready

+ Possible things that can be done= in PlatformBootManagerAfterConsole:

+ > Console post ac= tion:

+ > Dynamically switch output mode from 100x31 to = 80x25 for certain senarino

+ > Signal console ready plat= form customized event

+ > Run diagnostics like memory te= sting

+ > Connect certain devices

+ > D= ispatch aditional option roms

+ > Special boot: e.g.: US= B boot, enter UI

+**/

+VOID

+E=46= IAPI

+PlatformBootManagerAfterConsole (

+ VOI= D

+ )

+=7B

+ //

+= // Show the splash screen.

+ //

+ BootLogoEn= ableLogo ();

+

+ //

+ // Connec= t the rest of the devices.

+ //

+ EfiBootMana= gerConnectAll ();

+

+ //

+ // P= rocess QEMU's -kernel command line option. Note that the kernel booted
+ // this way should receive ACPI tables, which is why we con= nect all devices

+ // first (see above) -- PCI enumeration = blocks ACPI table installation, if

+ // there is a PCI host= .

+ //

+ TryRunningQemuKernel ();

+

+ //

+ // Enumerate all possible boot op= tions, then filter and reorder them based on

+ // the QEMU = configuration.

+ //

+ EfiBootManagerRefreshAl= lBootOption ();

+

+ //

+ // Reg= ister UE=46I Shell

+ //

+ PlatformRegister=46= vBootOption (

+ &gUefiShell=46ileGuid, L=22E=46I Intern= al Shell=22, LOAD=5FOPTION=5FACTIVE

+ );

+
+ RemoveStale=46v=46ileOptions ();

+ SetBootOrd= er=46romQemu ();

+=7D

+

+/**
+ This function is called each second during the boot manager= waits the

+ timeout.

+

+ =40pa= ram TimeoutRemain The remaining timeout.

+**/

+VOID

+E=46IAPI

+PlatformBootManagerWaitCall= back (

+ IN UINT16 TimeoutRemain

+ )
+=7B

+ E=46I=5FGRAPHICS=5FOUTPUT=5FBLT=5FPIXEL=5FUNIO= N Black;

+ E=46I=5FGRAPHICS=5FOUTPUT=5FBLT=5FPIXEL=5FUNION = White;

+ UINT16 Timeout;

+

+ Ti= meout =3D PcdGet16 (PcdPlatformBootTimeOut);

+

+ Black.Raw =3D 0x00000000;

+ White.Raw =3D 0x00=46=46=46= =46=46=46;

+

+ BootLogoUpdateProgress (
=
+ White.Pixel,

+ Black.Pixel,

+ L=22= Start boot option=22,

+ White.Pixel,

+ (Timeo= ut - TimeoutRemain) * 100 / Timeout,

+ 0

+ );=

+=7D

+

+/**

+ Th= e function is called when no boot option could be launched,

+ including platform recovery options and options pointing to applicatio= ns

+ built into firmware volumes.

+

=
+ If this function returns, BDS attempts to enter an infinite loop.<= /div>
+**/

+VOID

+E=46IAPI

<= div>+PlatformBootManagerUnableToBoot (

+ VOID

+ )

+=7B

+ E=46I=5FSTATUS Status;

<= div>+ E=46I=5FINPUT=5FKEY Key;

+ E=46I=5FBOOT=5FMANAGER=5FL= OAD=5FOPTION BootManagerMenu;

+ UINTN Index;

= +

+ //

+ // BootManagerMenu doesn't contain t= he correct information when return status

+ // is E=46I=5FN= OT=5F=46OUND.

+ //

+ Status =3D EfiBootManage= rGetBootManagerMenu (&BootManagerMenu);

+ if (E=46I=5FE= RROR (Status)) =7B

+ return;

+ =7D

<= div>+ //

+ // Normally BdsDxe does not print anything to th= e system console, but this is

+ // a last resort -- the end= -user will likely not see any DEBUG messages

+ // logged in= this situation.

+ //

+ // AsciiPrint () will= NULL-check gST->ConOut internally. We check gST->ConIn

+ // here to see if it makes sense to request and wait for a keypress.=

+ //

+ if (gST->ConIn =21=3D NULL) =7B
+ AsciiPrint (

+ =22%a: No bootable option or d= evice was found.=5Cn=22

+ =22%a: Press any key to enter the= Boot Manager Menu.=5Cn=22,

+ gEfiCallerBaseName,

=
+ gEfiCallerBaseName

+ );

+ Status =3D g= BS->Wait=46orEvent (1, &gST->ConIn->Wait=46orKey, &Index= );

+ ASSERT=5FE=46I=5FERROR (Status);

+ ASSER= T (Index =3D=3D 0);

+

+ //

+ //= Drain any queued keys.

+ //

+ while (=21E=46= I=5FERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) =7B=

+ //

+ // just throw away Key

= + //

+ =7D

+ =7D

+

+ for (;;) =7B

+ EfiBootManagerBoot (&BootManagerMenu= );

+ =7D

+=7D

diff --git a/Plat= form/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/PlatformBm.= h b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pla= tformBm.h

new file mode 100644

index 00000000= 00..f20c78252f

--- /dev/null

+++ b/Platform/L= oongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/PlatformBm.h
=40=40 -0,0 +1,112 =40=40

+/** =40file

<= div>+ Head file for BDS Platform specific code

+

<= div>+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rig= hts reserved.<BR>

+

+ SPDX-License-Iden= tifier: BSD-2-Clause-Patent

+

+**/

<= div>+

+=23ifndef PLAT=46ORM=5FBM=5FH=5F

+=23d= efine PLAT=46ORM=5FBM=5FH=5F

+

+=23include &l= t;Library/DevicePathLib.h>

+

+=23define DP= =5FNODE=5FLEN(Type) =7B (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >&= gt; 8) =7D

+

+=23define SERIAL=5FDXE=5F=46ILE= =5FGUID =7B =5C

+ 0xD3987D4B, 0x971A, 0x435=46, =5C
+ =7B 0x8C, 0xA=46, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 =7D =5C
+ =7D

+

+=23define ALIGN=5FUP(addr= , align) =5C

+ ((addr + (typeof (addr)) align - 1) & =7E= ((typeof (addr)) align - 1))

+

+=23pragma pac= k (1)

+typedef struct =7B

+ VENDOR=5FDEVICE=5F= PATH SerialDxe;

+ UART=5FDEVICE=5FPATH Uart;

= + VENDOR=5FDE=46INED=5FDEVICE=5FPATH TermType;

+ E=46I=5FDE= VICE=5FPATH=5FPROTOCOL End;

+=7D PLAT=46ORM=5FSERIAL=5FCONS= OLE;

+=23pragma pack ()

+

+=23p= ragma pack (1)

+typedef struct =7B

+ USB=5FCL= ASS=5FDEVICE=5FPATH Keyboard;

+ E=46I=5FDEVICE=5FPATH=5FPRO= TOCOL End;

+=7D PLAT=46ORM=5FUSB=5FKEYBOARD;

= +=23pragma pack ()

+

+/**

+ Che= ck if the handle satisfies a particular condition.

+
<= br>
+ =40param=5Bin=5D Handle The handle to check.

+ =40= param=5Bin=5D ReportText A caller-allocated string passed in for reportin= g

+ purposes. It must never be NULL.

+
<= br>
+ =40retval TRUE The condition is satisfied.

+ =40r= etval =46ALSE Otherwise. This includes the case when the condition could = not

+ be fully evaluated due to an error.

+**= /

+typedef

+BOOLEAN

+(E=46IAPI = *=46ILTER=5F=46UNCTION) (

+ IN E=46I=5FHANDLE Handle,
=
+ IN CONST CHAR16 *ReportText

+ );

+=

+/**

+ Process a handle.

+
+ =40param=5Bin=5D Handle The handle to process.

+ =40param=5Bin=5D ReportText A caller-allocated string passed in for re= porting

+ purposes. It must never be NULL.

+*= */

+typedef

+VOID

+(E=46IAPI *C= ALLBACK=5F=46UNCTION) (

+ IN E=46I=5FHANDLE Handle,
+ IN CONST CHAR16 *ReportText

+ );

+
+/**

+ * execute from kernel entry point.
+ *

+ * =40param=5Bin=5D Argc The count of args.<= /div>
+ * =40param=5Bin=5D Argv The pointer to args array.
<= br>
+ * =40param=5Bin=5D Bpi The pointer to bootparaminterface struct= .

+ * =40param=5Bin=5D Vec The fourth args for kernel.
+ ***/

+typedef

+VOID

+(E=46IAPI *E=46I=5FKERNEL=5FENTRY=5FPOINT) (

+ IN UINTN A= rgc,

+ IN VOID *Argv,

+ IN VOID *Bpi,
+ IN VOID *Vec

+ );

+

+/= **

+ Download the kernel, the initial ramdisk, and the kern= el command line from

+ QEMU's fw=5Fcfg. Construct a minimal= Simple=46ileSystem that contains the two

+ image files, an= d load and start the kernel from it.

+

+ The = kernel will be instructed via its command line to load the initrd from
+ the same Simple =46ileSystem.

+

+ =40retval E=46I=5FNOT=5F=46OUND Kernel image was not found.

<= div>+ =40retval E=46I=5FOUT=5FO=46=5FRESOURCES Memory allocation failed.<= /div>
+ =40retval E=46I=5FPROTOCOL=5FERROR Unterminated kernel co= mmand line.

+

+ =40return Error codes from an= y of the underlying

+ functions. On success, the function d= oesn't

+ return.

+**/

+E=46I=5F= STATUS

+E=46IAPI

+TryRunningQemuKernel (
+ VOID

+ );

+

+=23end= if // PLAT=46ORM=5FBM=5FH=5F

diff --git a/Platform/Loongson= /LoongArchQemuPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.i= nf b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pl= atformBootManagerLib.inf

new file mode 100644

index 0000000000..0ea6fea5c5

--- /dev/null

+= ++ b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Pl= atformBootManagerLib.inf

=40=40 -0,0 +1,75 =40=40

=
+=23=23 =40file

+=23 Implementation for PlatformBootMa= nagerLib library class interfaces.

+=23

+=23 = Copyright (c) 2022 Loongson Technology Corporation Limited. All rights re= served.<BR>

+=23

+=23 SPDX-License-Iden= tifier: BSD-2-Clause-Patent

+=23

+=23=23
+

+=5BDefines=5D

+ IN=46=5FVERSION = =3D 0x00010005

+ BASE=5FNAME =3D PlatformBootManagerLib
+ =46ILE=5FGUID =3D 469184E8-=46ADA-41E4-8823-012CA19B40D4
+ MODULE=5FTYPE =3D DXE=5FDRIVER

+ VERSION=5FSTR= ING =3D 1.0

+ LIBRARY=5FCLASS =3D PlatformBootManagerLib=7C= DXE=5FDRIVER

+

+=23

+=23 VALID=5F= ARCHITECTURES =3D LOONGARCH64

+=23

+
+=5BSources=5D

+ PlatformBm.c

+ QemuKer= nel.c

+

+=5BPackages=5D

+ Platf= orm/Loongson/LoongArchQemuPkg/Loongson.dec

+ MdeModulePkg/M= deModulePkg.dec

+ MdePkg/MdePkg.dec

+ OvmfPkg= /OvmfPkg.dec

+ ShellPkg/ShellPkg.dec

+
<= br>
+=5BLibraryClasses=5D

+ BaseLib

+ Bas= eMemoryLib

+ BootLogoLib

+ DebugLib

=
+ DevicePathLib

+ MemoryAllocationLib

+ = PcdLib

+ PrintLib

+ QemuBootOrderLib
+ QemuLoadImageLib

+ Qemu=46wCfgLib

+ U= efiBootManagerLib

+ UefiBootServicesTableLib

= + UefiLib

+ UefiRuntimeServicesTableLib

+
+=5B=46ixedPcd=5D

+ gEfiMdePkgTokenSpaceGuid.Pcd= UartDefaultBaudRate

+ gEfiMdePkgTokenSpaceGuid.PcdUartDefau= ltDataBits

+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity<= /div>
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits

=
+

+=5BPcd=5D

+ gEfiMdePkgTokenSpaceGuid.= PcdPlatformBootTimeOut

+

+=5BGuids=5D
+ gEfi=46ileInfoGuid

+ gEfi=46ileSystemInfoGuid
+ gEfi=46ileSystemVolumeLabelInfoIdGuid

+ gEfiEnd= OfDxeEventGroupGuid

+ gRootBridgesConnectedEventGroupGuid
+ gUefiShell=46ileGuid

+ gEfiLoongsonBootparam= sTableGuid =23=23 SOMETIMES=5FPRODUCES =23=23 SystemTable

+= gEfiTtyTermGuid

+

+=5BProtocols=5D

=
+ gEfiDevicePathProtocolGuid

+ gEfi=46irmwareVolume2Pr= otocolGuid

+ gEfiGraphicsOutputProtocolGuid

+= gEfiLoadedImageProtocolGuid

+ gEfiPciRootBridgeIoProtocolG= uid

+ gEfiSimple=46ileSystemProtocolGuid

diff= --git a/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLi= b/QemuKernel.c b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootM= anagerLib/QemuKernel.c

new file mode 100644

i= ndex 0000000000..386003a8d7

--- /dev/null

+++= b/Platform/Loongson/LoongArchQemuPkg/Library/PlatformBootManagerLib/Qemu= Kernel.c

=40=40 -0,0 +1,81 =40=40

+/** =40fil= e

+ Try to run Linux kernel.

+

= + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights = reserved.<BR>

+

+ SPDX-License-Identifi= er: BSD-2-Clause-Patent

+

+ =40par Glossary:<= /div>
+ - mem - Memory

+ - Bpi - Boot Parameter Int= erface

+ - =46wCfg - =46irmWare Configure

+**= /

+

+=23include <Library/QemuLoadImageLib.= h>

+=23include <Library/ReportStatusCodeLib.h>
+

+=23include <Library/BaseLib.h>
+=23include <Library/BaseMemoryLib.h>

+=23inclu= de <Library/DebugLib.h>

+=23include <Library/Devic= ePathLib.h>

+=23include <Library/MemoryAllocationLib.= h>

+=23include <Library/UefiBootServicesTableLib.h>= ;

+=23include <Library/UefiLib.h>

+=23i= nclude <Library/UefiRuntimeServicesTableLib.h>

+
+/**

+ Download the kernel, the initial ramdisk, = and the kernel command line from

+ QEMU's fw=5Fcfg. Constru= ct a minimal Simple=46ileSystem that contains the two

+ ima= ge files, and load and start the kernel from it.

+
+ The kernel will be instructed via its command line to load the in= itrd from

+ the same Simple =46ileSystem.

+
+ =40retval E=46I=5FNOT=5F=46OUND Kernel image was not found= .

+ =40retval E=46I=5FOUT=5FO=46=5FRESOURCES Memory allocat= ion failed.

+ =40retval E=46I=5FPROTOCOL=5FERROR Unterminat= ed kernel command line.

+

+ =40return Error c= odes from any of the underlying

+ functions. On success, th= e function doesn't

+ return.

+**/

+E=46I=5FSTATUS

+TryRunningQemuKernel (

+ = VOID

+ )

+=7B

+ E=46I=5FSTATUS = Status;

+ E=46I=5FHANDLE KernelImageHandle;

+=

+ Status =3D QemuLoadKernelImage (&KernelImageHandle);=

+ if (E=46I=5FERROR (Status)) =7B

+ return S= tatus;

+ =7D

+

+ //

+ // Signal the E=46I=5FEVENT=5FGROUP=5FREADY=5FTO=5FBOOT event.
=
+ //

+ EfiSignalEventReadyToBoot ();

+

+ REPORT=5FSTATUS=5FCODE (

+ E=46I=5FPROGR= ESS=5FCODE,

+ (E=46I=5FSO=46TWARE=5FDXE=5FBS=5FDRIVER =7C E= =46I=5FSW=5FDXE=5FBS=5FPC=5FREADY=5FTO=5FBOOT=5FEVENT)

+ );=

+

+ //

+ // Start the image.
+ //

+ Status =3D QemuStartKernelImage (&K= ernelImageHandle);

+ if (E=46I=5FERROR (Status)) =7B
<= br>
+ DEBUG ((

+ DEBUG=5FERROR,

+ =22%a: = QemuStartKernelImage(): %r=5Cn=22,

+ =5F=5F=46UNCTION=5F=5F= ,

+ Status

+ ));

+ =7D
+

+ QemuUnloadKernelImage (KernelImageHandle);
<= br>
+

+ return Status;

+=7D

--

2.31.1
--636e1a8a_189805c2_1e57b--