Date   

Re: [EXTERNAL] Re: Soft Feature Freeze starts now for edk2-stable202008

Bret Barkelew
 

Not yet, which is also why I’m raising the note ASAP. I’ll respond to the other feedback today to get that moving.

 

- Bret

 

From: Laszlo Ersek
Sent: Monday, August 17, 2020 1:46 PM
To: Bret Barkelew; devel@edk2.groups.io; liming.gao; announce@edk2.groups.io
Cc: Leif Lindholm; afish@...; Kinney, Michael D; Guptha, Soumya K
Subject: [EXTERNAL] Re: Soft Feature Freeze starts now for edk2-stable202008

 

Hi Bret,

On 08/17/20 20:14, Bret Barkelew wrote:
> I would like Variable Policy to be considered for this feature freeze. I have a couple of documentation things to respond to, but no serious functionality questions (that I know of).

Has review completed on the series (before entering the soft feature
freeze)?

https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FSoftFeatureFreeze&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C39b20e742dff4f810fa708d842eea26a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637332939979144622&sdata=%2BsSEmkhvkuzZqSUxNbK9cWWWnweRVmN0SG7HheLAIPc%3D&reserved=0

(Please note that I don't insist on this particular definition of the
SFF; it's what we have modeled on the QEMU soft feature freeze
definition. It's not carved in stone. It's just what we have for now.)

Thanks
Laszlo

 


Re: Soft Feature Freeze starts now for edk2-stable202008

Laszlo Ersek
 

Hi Bret,

On 08/17/20 20:14, Bret Barkelew wrote:
I would like Variable Policy to be considered for this feature freeze. I have a couple of documentation things to respond to, but no serious functionality questions (that I know of).
Has review completed on the series (before entering the soft feature
freeze)?

https://github.com/tianocore/tianocore.github.io/wiki/SoftFeatureFreeze

(Please note that I don't insist on this particular definition of the
SFF; it's what we have modeled on the QEMU soft feature freeze
definition. It's not carved in stone. It's just what we have for now.)

Thanks
Laszlo


Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand

Laszlo Ersek
 

On 08/17/20 20:29, Vladimir Olovyannikov wrote:
-----Original Message-----
From: Laszlo Ersek <lersek@redhat.com>
Sent: Monday, August 17, 2020 11:01 AM
To: Rabeda, Maciej <maciej.rabeda@linux.intel.com>; Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>; Gao, Zhichao
<zhichao.gao@intel.com>; devel@edk2.groups.io
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>; Wu, Jiaxin
<jiaxin.wu@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Ni, Ray
<ray.ni@intel.com>; Gao, Liming <liming.gao@intel.com>; Nd
<nd@arm.com>
Subject: Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand

On 08/17/20 19:15, Rabeda, Maciej wrote:
Hi Vladimir,

I cannot apply the patch via 'git am'.
Is your git configured in a manner described here?
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt
-git-guide-for-edk2-contributors-and-maintainers
Hi Rabeda,
Yes, I followed the page. I did not run the SetupGit.py though.


Laszlo,

Were you able to apply this patch from .eml file?
Yes, but I had to use some tricks (implemented by my colleague Paolo in a
python script) to undo the damage caused by the "quoted-printable"
content-transfer-encoding on the posting.

Our recommended Content-Transfer-Encoding (that is,
"sendemail.transferEncoding") is "8bit", or even "base64".
quoted-printable is practically impossible to get functional, with the
hard
CRLF line endings in edk2.

"BaseTools/Scripts/SetupGit.py" does set "8bit".
Thank you for notice Laszlo,
So, should I run this script and re-send the patch as v6?
I think that would be useful, yes -- and if you have made no changes
since v5, you can also post it as "v5 RESEND". If you've implemented
some changes meanwhile, then please post it as v6 indeed.

Thanks
Laszlo


Re: [PATCH 0/3] Platform/RasberryPi: Thermal zone

Jeremy Linton
 

Hi,

On 8/17/20 9:31 AM, Ard Biesheuvel via groups.io wrote:
On 8/14/20 1:00 AM, Jeremy Linton wrote:
This set creates a basic thermal zone, which reads the
SOC temp via a direct register read in AML. It also
adds an active cooling policy using a GPIO pin for fan
control that can optionally be enabled/disabled by the
user from the BDS.

With the fan enabled it should be possible to see the
soc temp like:
^ That should have read something like:

"Even without the fan enabled it is possible to see the SOC temp like:"


# sensors
acpitz-acpi-0
Adapter: ACPI interface
temp1:        +57.6C  (crit = +90.0C)

and the fan state may be read/cycled with:

/sys/bus/acpi/devices/PNP0C06:00/PNP0C0B:00/physical_node/thermal_cooling/cur_state

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>

Jeremy Linton (3):
   Platform/RaspberryPi4: Add a basic thermal zone
   Platform/RaspberryPi4: Create ACPI fan object
   Platform/RaspberryPi: Add entry for user fan control
I like this code a lot. It is very helpful to have working sample AML code that implements a thermal zone. Could you elaborate on the additional components that are needed for this? Is this a standard cape (or whatever rpi calls it)? I assume the fan just switches between 0 and max rpm depending on the actual temp wrt the trip point?

I've got something similar to this circuit: https://www.raspberrypi.org/forums/viewtopic.php?t=194621#p1220502 wired up. There are a number of variations on the web (https://www.instructables.com/id/PWM-Regulated-Fan-Based-on-CPU-Temperature-for-Ras/), frequently including python control scripts, which are unnecessary given this AML/patch. Most of the variation is simply matching an appropriate resistor between the GPIO and transistor base for the given transistor's gain.

A board which implements a similar circuit can be purchased here: https://shop.pimoroni.com/products/fan-shim

Most of these circuits are designed for simple On/Off control. So as it stands, the kernel calls the ON() method, when it polls the zone temp, and discovers that it exceeds the active cooling threshold. Or the OFF() if the temp falls below. The slow polling and large heatsink on my rpi tends to keep it from excessive hunting/cycling since the kernel doesn't implement much in the way of hysteresis control.

The GPIO pin I selected also (AFAIK) has a PWM function that could be leveraged in the future for variable speed control. That said, most of these little 5V fans seem to be basically silent (well the ones I have, or they are 12V already running at low voltage), so there is little advantage to slowing them down.

The big variation is which GPIO controls the fan. This patch at the moment has a #define setting the pin, but the general plan was to add some additional user controllable options for board/GPIO pin selection. Originally I was planning on just compiling the ASL multiple times for each GPIO and then picking one at runtime, but now I'm thinking dynamically editing the binary AML before calling InstallTable() on it might be a better choice to reduce bloat.

A few of the fan boards/cases implement their own fan controllers with programmable thermal profiles over I2C. This patch won't support those boards. (yet! :)



  Platform/RaspberryPi/AcpiTables/Dsdt.asl           | 31 ++++++++
  Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 55 ++++++++++++++
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf    |  3 +
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni |  5 ++
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr | 17 +++++
  .../RaspberryPi/Drivers/ConfigDxe/SsdtThermal.asl  | 83 ++++++++++++++++++++++
  Platform/RaspberryPi/Include/ConfigVars.h          |  4 ++
  Platform/RaspberryPi/RPi3/RPi3.dsc                 |  5 ++
  Platform/RaspberryPi/RPi4/RPi4.dsc                 |  8 +++
  Platform/RaspberryPi/RaspberryPi.dec               |  1 +
  .../Bcm27xx/Include/IndustryStandard/Bcm2711.h     |  2 +
  11 files changed, 214 insertions(+)
  create mode 100644 Platform/RaspberryPi/Drivers/ConfigDxe/SsdtThermal.asl


Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand

Vladimir Olovyannikov
 

-----Original Message-----
From: Laszlo Ersek <lersek@redhat.com>
Sent: Monday, August 17, 2020 11:01 AM
To: Rabeda, Maciej <maciej.rabeda@linux.intel.com>; Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>; Gao, Zhichao
<zhichao.gao@intel.com>; devel@edk2.groups.io
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>; Wu, Jiaxin
<jiaxin.wu@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Ni, Ray
<ray.ni@intel.com>; Gao, Liming <liming.gao@intel.com>; Nd
<nd@arm.com>
Subject: Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand

On 08/17/20 19:15, Rabeda, Maciej wrote:
Hi Vladimir,

I cannot apply the patch via 'git am'.
Is your git configured in a manner described here?
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt
-git-guide-for-edk2-contributors-and-maintainers
Hi Rabeda,
Yes, I followed the page. I did not run the SetupGit.py though.


Laszlo,

Were you able to apply this patch from .eml file?
Yes, but I had to use some tricks (implemented by my colleague Paolo in a
python script) to undo the damage caused by the "quoted-printable"
content-transfer-encoding on the posting.

Our recommended Content-Transfer-Encoding (that is,
"sendemail.transferEncoding") is "8bit", or even "base64".
quoted-printable is practically impossible to get functional, with the
hard
CRLF line endings in edk2.

"BaseTools/Scripts/SetupGit.py" does set "8bit".
Thank you for notice Laszlo,
So, should I run this script and re-send the patch as v6?

Thank you,
Vladimir

Thanks
Laszlo


Re: Soft Feature Freeze starts now for edk2-stable202008

Bret Barkelew
 

I would like Variable Policy to be considered for this feature freeze. I have a couple of documentation things to respond to, but no serious functionality questions (that I know of).

- Bret


From: devel@edk2.groups.io <devel@edk2.groups.io> on behalf of Liming Gao via groups.io <liming.gao@...>
Sent: Friday, August 14, 2020 1:16:41 AM
To: devel@edk2.groups.io <devel@edk2.groups.io>; announce@edk2.groups.io <announce@edk2.groups.io>
Cc: Laszlo Ersek <lersek@...>; Leif Lindholm <leif@...>; afish@... <afish@...>; Kinney, Michael D <michael.d.kinney@...>; Guptha, Soumya K <soumya.k.guptha@...>
Subject: [EXTERNAL] [edk2-devel] Soft Feature Freeze starts now for edk2-stable202008
 

Hi, all

  We will enter into Soft Feature Freeze phase. In this phase, the feature under review will not be allowed to be pushed. The feature passed review can still be merged. Now, two features have passed code review. If no other comments, I will merge them into this stable tag. They are: https://edk2.groups.io/g/devel/message/64176 SEV-ES guest support, https://edk2.groups.io/g/devel/message/64283 Add a plugin to check Ecc issues for edk2 on open ci.

 

The patch review can continue without break in edk2 community. If the patch is sent before Soft Feature Freeze, and plans to catch this stable tag, the patch contributor need reply to his patch and notify edk2 community. If the patch is sent after Soft Feature Freeze, and plans to catch this stable tag, please add edk2-stable202008 key words in the patch title and BZ, so the community know this patch target and give the feedback.

 

Below is edk2-stable202008 tag planning https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning Proposed Schedule

Date (00:00:00 UTC-8) Description

2020-06-03  Beginning of development

2020-08-07  Feature Planning Freeze

2020-08-14  Soft Feature Freeze

2020-08-21  Hard Feature Freeze

2020-08-28  Release

 

Thanks

Liming


Re: [PATCH 3/3] Platform/RaspberryPi: Add entry for user fan control

Jeremy Linton
 

Hi,

Thanks for taking a look at this, I will roll another version with the suggested changes. It seems my space '(' rules are broken :)

On 8/17/20 6:10 AM, Pete Batard wrote:
More minor style issues:
On 2020.08.14 00:00, Jeremy Linton wrote:
Add a menu item that allows the user to enable GPIO based
fan control via SSDT. This should only be seen/enabled on RPI4
because that is what its been tested with. As of this commit
its currently limited to only operating on a single GPIO pin (19).

Given GPIO pin current limitations its likely that a bit of
additional circuitry is required to drive a fan, and the GPIO
high/low signal can only be used as a enable/disable signal. A
search for "rpi npn gpio fan" or similar should turn up some
hits for how to do this simply.

It appears there are a couple boards (fan SHIM) which operate this
way, and probably should have custom menu items/SSDT edits as
people acquire the boards and test them.

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
  Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 55 ++++++++++++++++++++++
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf    |  3 ++
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni |  5 ++
  .../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr | 17 +++++++
  Platform/RaspberryPi/Include/ConfigVars.h          |  4 ++
  Platform/RaspberryPi/RPi3/RPi3.dsc                 |  5 ++
  Platform/RaspberryPi/RPi4/RPi4.dsc                 |  8 ++++
  Platform/RaspberryPi/RaspberryPi.dec               |  1 +
  .../Bcm27xx/Include/IndustryStandard/Bcm2711.h     |  2 +
  9 files changed, 100 insertions(+)

diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
index af54136ade..f10347be64 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
@@ -15,6 +15,7 @@
  #include <Library/AcpiLib.h>

  #include <Library/DebugLib.h>

  #include <Library/DevicePathLib.h>

+#include <Library/DxeServicesLib.h>

  #include <Library/DxeServicesTableLib.h>

  #include <Library/GpioLib.h>

  #include <Library/HiiLib.h>

@@ -22,6 +23,7 @@
  #include <Library/NetLib.h>

  #include <Library/UefiBootServicesTableLib.h>

  #include <Library/UefiRuntimeServicesTableLib.h>

+#include <Protocol/AcpiTable.h>

  #include <Protocol/BcmGenetPlatformDevice.h>

  #include <Protocol/RpiFirmware.h>

  #include <ConfigVars.h>

@@ -246,6 +248,14 @@ SetupVariables (
      ASSERT_EFI_ERROR (Status);

    }


+  Size = sizeof (UINT32);

+  Status = gRT->GetVariable (L"FanOnGpio",

+                  &gConfigDxeFormSetGuid,

+                  NULL, &Size, &Var32);

+  if (EFI_ERROR (Status)) {

+    PcdSet32 (PcdFanOnGpio, PcdGet32 (PcdFanOnGpio));

+  }

+

    Size = sizeof(AssetTagVar);
Space before '('



    Status = gRT->GetVariable(L"AssetTag",
Space before '('


@@ -368,6 +378,7 @@ ApplyVariables (
    UINT32 CpuClock = PcdGet32 (PcdCpuClock);

    UINT32 CustomCpuClock = PcdGet32 (PcdCustomCpuClock);

    UINT32 Rate = 0;

+  UINT32 FanOnGpio = PcdGet32 (PcdFanOnGpio);


    switch (CpuClock) {

    case CHIPSET_CPU_CLOCK_LOW:

@@ -565,8 +576,49 @@ ApplyVariables (
      GpioPinFuncSet (23, GPIO_FSEL_INPUT);

      GpioPinFuncSet (24, GPIO_FSEL_INPUT);

    }

+

+  if (FanOnGpio) {

+    DEBUG ((DEBUG_INFO, "Fan enabled on GPIO %d\n", FanOnGpio));

+    GpioPinFuncSet(FanOnGpio, GPIO_FSEL_OUTPUT);
Space before '('

+  }

  }


+EFI_STATUS

+FindInstallSsdt(UINT64 OemTableId)
Space before '('


+{

+  EFI_ACPI_TABLE_PROTOCOL         *AcpiTable;

+  UINTN                           Index;

+  EFI_ACPI_DESCRIPTION_HEADER     *Ssdt;

+  UINTN                           SsdtSize;

+  EFI_STATUS                      Status;

+  UINTN                           TableKey;

+

+

+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL,

+                                (VOID **)&AcpiTable);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  for (Index = 0; !EFI_ERROR(Status); Index++) {
Space before '('


+    Status = GetSectionFromFv (&gEfiCallerIdGuid, EFI_SECTION_RAW, Index,

+                               (VOID **)&Ssdt, &SsdtSize);

+    if (Ssdt->OemTableId == OemTableId)

+        break;
Indentation should be 2 spaces after 'if'


+    SsdtSize = 0;

+  }

+

+  if (SsdtSize > 0) {

+    Status = AcpiTable->InstallAcpiTable (AcpiTable, Ssdt, SsdtSize,

+                                          &TableKey);

+    if (EFI_ERROR (Status)) {

+      DEBUG ((DEBUG_WARN, "%a: failed to install SSDT table %r\n",

+              __FUNCTION__, Status));

+    }

+  }

+

+  return Status;

+}


  EFI_STATUS

  EFIAPI

@@ -620,6 +672,9 @@ ConfigInitialize (
        PcdGet32 (PcdSystemTableMode) == SYSTEM_TABLE_MODE_BOTH) {

       Status = LocateAndInstallAcpiFromFv (&mAcpiTableFile);

       ASSERT_EFI_ERROR (Status);

+     if (PcdGet32 (PcdFanOnGpio)) {

+         FindInstallSsdt(SIGNATURE_64 ('R', 'P', 'I', 'T', 'H', 'F', 'A', 'N'));
Space before '(' and indentation should be 2 spaces after 'if'


+     }

    }


    Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RegisterDevices,

diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
index cdce35bc74..fe3a01a570 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
@@ -28,6 +28,7 @@
    ConfigDxeFormSetGuid.h

    ConfigDxeHii.vfr

    ConfigDxeHii.uni

+  SsdtThermal.asl

    XhciQuirk.c


  [Packages]

@@ -46,6 +47,7 @@
    AcpiLib

    BaseLib

    DebugLib

+  DxeServicesLib

    DxeServicesTableLib

    GpioLib

    HiiLib

@@ -89,6 +91,7 @@
    gRaspberryPiTokenSpaceGuid.PcdSystemTableMode

    gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB

    gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB

+  gRaspberryPiTokenSpaceGuid.PcdFanOnGpio


  [Depex]

    gPcdProtocolGuid AND gRaspberryPiFirmwareProtocolGuid

diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni
index 03763710a1..491d022fff 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni
@@ -48,6 +48,11 @@
  #string STR_ADVANCED_SYSTAB_BOTH     #language en-US "ACPI + Devicetree"

  #string STR_ADVANCED_SYSTAB_DT       #language en-US "Devicetree"


+#string STR_ADVANCED_FANONGPIO_PROMPT #language en-US "ACPI fan control"

+#string STR_ADVANCED_FANONGPIO_HELP   #language en-US "Cycle a fan via GPIO-19 if temp exceeds 60C"

+#string STR_ADVANCED_FANONGPIO_OFF    #language en-US "Disabled"

+#string STR_ADVANCED_FANONGPIO_ON     #language en-US "Enabled"

+

  #string STR_ADVANCED_ASSET_TAG_PROMPT #language en-US "Asset Tag"

  #string STR_ADVANCED_ASSET_TAG_HELP   #language en-US "Set the system Asset Tag"


diff --git a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr
index d5615d7af0..0a5e4163e8 100644
--- a/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr
+++ b/Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr
@@ -10,6 +10,7 @@
  #include <Guid/HiiPlatformSetupFormset.h>

  #include "ConfigDxeFormSetGuid.h"

  #include <ConfigVars.h>

+#include <IndustryStandard/Bcm2711.h>


  //

  // EFI Variable attributes

@@ -45,6 +46,11 @@ formset
        name  = RamLimitTo3GB,

        guid  = CONFIGDXE_FORM_SET_GUID;


+    efivarstore ADVANCED_FAN_ON_GPIO_VARSTORE_DATA,

+      attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,

+      name  = FanOnGpio,

+      guid  = CONFIGDXE_FORM_SET_GUID;

+

      efivarstore SYSTEM_TABLE_MODE_VARSTORE_DATA,

        attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,

        name  = SystemTableMode,

@@ -174,6 +180,17 @@ formset
              option text = STRING_TOKEN(STR_ADVANCED_SYSTAB_DT), value = SYSTEM_TABLE_MODE_DT, flags = DEFAULT;

          endoneof;


+#if (RPI_MODEL == 4)

+        grayoutif NOT ideqval SystemTableMode.Mode == SYSTEM_TABLE_MODE_ACPI;

+          oneof varid = FanOnGpio.Enabled,

+              prompt      = STRING_TOKEN(STR_ADVANCED_FANONGPIO_PROMPT),

+              help        = STRING_TOKEN(STR_ADVANCED_FANONGPIO_HELP),

+              flags       = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED,

+              option text = STRING_TOKEN(STR_ADVANCED_FANONGPIO_OFF), value = 0, flags = DEFAULT;

+              option text = STRING_TOKEN(STR_ADVANCED_FANONGPIO_ON), value = GPIO_FAN_PIN, flags = 0;

+          endoneof;

+        endif;

+#endif

          string varid = AssetTag.AssetTag,

              prompt  = STRING_TOKEN(STR_ADVANCED_ASSET_TAG_PROMPT),

              help    = STRING_TOKEN(STR_ADVANCED_ASSET_TAG_HELP),

diff --git a/Platform/RaspberryPi/Include/ConfigVars.h b/Platform/RaspberryPi/Include/ConfigVars.h
index b1689b004d..1a40469bfa 100644
--- a/Platform/RaspberryPi/Include/ConfigVars.h
+++ b/Platform/RaspberryPi/Include/ConfigVars.h
@@ -69,6 +69,10 @@ typedef struct {
  } ADVANCED_RAM_LIMIT_TO_3GB_VARSTORE_DATA;


  typedef struct {

+  UINT32 Enabled;

+} ADVANCED_FAN_ON_GPIO_VARSTORE_DATA;

+

+typedef struct {

  #define SYSTEM_TABLE_MODE_ACPI 0

  #define SYSTEM_TABLE_MODE_BOTH 1

  #define SYSTEM_TABLE_MODE_DT   2

diff --git a/Platform/RaspberryPi/RPi3/RPi3.dsc b/Platform/RaspberryPi/RPi3/RPi3.dsc
index 0998d8366c..cef8932ca2 100644
--- a/Platform/RaspberryPi/RPi3/RPi3.dsc
+++ b/Platform/RaspberryPi/RPi3/RPi3.dsc
@@ -499,6 +499,11 @@
gRaspberryPiTokenSpaceGuid.PcdSystemTableMode|L"SystemTableMode"|gConfigDxeFormSetGuid|0x0|1


    #

+  # Enable a fan in the ACPI thermal zone on GPIO pin #

+  #

+ gRaspberryPiTokenSpaceGuid.PcdFanOnGpio|L"FanOnGpio"|gConfigDxeFormSetGuid|0x0|0

+

+  #

    # Common UEFI ones.

    #


diff --git a/Platform/RaspberryPi/RPi4/RPi4.dsc b/Platform/RaspberryPi/RPi4/RPi4.dsc
index baa7e63483..9d0eaf10a1 100644
--- a/Platform/RaspberryPi/RPi4/RPi4.dsc
+++ b/Platform/RaspberryPi/RPi4/RPi4.dsc
@@ -510,6 +510,14 @@
gRaspberryPiTokenSpaceGuid.PcdSystemTableMode|L"SystemTableMode"|gConfigDxeFormSetGuid|0x0|0


    #

+  # Enable a fan in the ACPI thermal zone on GPIO pin #

+  #

+  # 0  - DISABLED

+  # 19 - Enabled on pin 19

+  #

+ gRaspberryPiTokenSpaceGuid.PcdFanOnGpio|L"FanOnGpio"|gConfigDxeFormSetGuid|0x0|0

+

+  #

    # Common UEFI ones.

    #


diff --git a/Platform/RaspberryPi/RaspberryPi.dec b/Platform/RaspberryPi/RaspberryPi.dec
index c71177a2f7..a73650f2c3 100644
--- a/Platform/RaspberryPi/RaspberryPi.dec
+++ b/Platform/RaspberryPi/RaspberryPi.dec
@@ -66,3 +66,4 @@
    gRaspberryPiTokenSpaceGuid.PcdSystemTableMode|1|UINT32|0x0000001B

    gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|0|UINT32|0x00000019

    gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|0|UINT32|0x0000001A

+  gRaspberryPiTokenSpaceGuid.PcdFanOnGpio|0|UINT32|0x0000001C

diff --git a/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h b/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
index e9c81cafa1..7d9ea5d35c 100644
--- a/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
+++ b/Silicon/Broadcom/Bcm27xx/Include/IndustryStandard/Bcm2711.h
@@ -86,4 +86,6 @@
  #define GENET_BASE_ADDRESS         FixedPcdGet64 (PcdBcmGenetRegistersAddress)

  #define GENET_LENGTH               0x00010000


+#define GPIO_FAN_PIN               19 // fan shim uses GPIO 18

+

  #endif /* BCM2711_H__ */
Reviewed-by: Pete Batard <pete@akeo.ie>


Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand

Laszlo Ersek
 

On 08/17/20 19:15, Rabeda, Maciej wrote:
Hi Vladimir,

I cannot apply the patch via 'git am'.
Is your git configured in a manner described here?
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers


Laszlo,

Were you able to apply this patch from .eml file?
Yes, but I had to use some tricks (implemented by my colleague Paolo in
a python script) to undo the damage caused by the "quoted-printable"
content-transfer-encoding on the posting.

Our recommended Content-Transfer-Encoding (that is,
"sendemail.transferEncoding") is "8bit", or even "base64".
quoted-printable is practically impossible to get functional, with the
hard CRLF line endings in edk2.

"BaseTools/Scripts/SetupGit.py" does set "8bit".

Thanks
Laszlo


Re: [PATCH v15 00/46] SEV-ES guest support

Lendacky, Thomas
 

Yes, a big thank you to everyone involved!

Tom

On 8/17/20 12:03 PM, Laszlo Ersek wrote:
On 08/17/20 06:09, Gao, Liming wrote:
This patch set have been merged edk2 7f7f511c5a74676523ed48435350f6e35282b62b..7f0b28415cb464832155d5b3ff6eb63612f58645
Thank you!
Laszlo

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Liming Gao
Sent: 2020年8月14日 9:20
To: Laszlo Ersek <lersek@redhat.com>; Tom Lendacky <thomas.lendacky@amd.com>; devel@edk2.groups.io
Cc: Brijesh Singh <brijesh.singh@amd.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Ni, Ray <ray.ni@intel.com>; Andrew Fish <afish@apple.com>; Anthony Perard <anthony.perard@citrix.com>; You, Benjamin <benjamin.you@intel.com>; Bi, Dandan <dandan.bi@intel.com>; Dong, Guo <guo.dong@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Julien Grall <julien@xen.org>; Leif Lindholm <leif@nuviainc.com>; Ma, Maurice <maurice.ma@intel.com>
Subject: Re: [edk2-devel] [PATCH v15 00/46] SEV-ES guest support

Laszlo:

-----Original Message-----
From: Laszlo Ersek <lersek@redhat.com>
Sent: 2020年8月14日 3:54
To: Tom Lendacky <thomas.lendacky@amd.com>; devel@edk2.groups.io
Cc: Brijesh Singh <brijesh.singh@amd.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Ni, Ray <ray.ni@intel.com>; Andrew Fish <afish@apple.com>; Anthony Perard <anthony.perard@citrix.com>; You, Benjamin <benjamin.you@intel.com>; Bi, Dandan <dandan.bi@intel.com>; Dong, Guo <guo.dong@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Julien Grall <julien@xen.org>; Leif Lindholm <leif@nuviainc.com>; Ma, Maurice <maurice.ma@intel.com>
Subject: Re: [PATCH v15 00/46] SEV-ES guest support

On 08/13/20 15:22, Tom Lendacky wrote:
From: Tom Lendacky <thomas.lendacky@amd.com>

This patch series provides support for running EDK2/OVMF under SEV-ES.

Secure Encrypted Virtualization - Encrypted State (SEV-ES) expands on
the SEV support to protect the guest register state from the
hypervisor. See
"AMD64 Architecture Programmer's Manual Volume 2: System Programming",
section "15.35 Encrypted State (SEV-ES)" [1].

In order to allow a hypervisor to perform functions on behalf of a
guest, there is architectural support for notifying a guest's
operating system when certain types of VMEXITs are about to occur.
This allows the guest to selectively share information with the
hypervisor to satisfy the requested function. The notification is
performed using a new exception, the VMM Communication exception
(#VC). The information is shared through the Guest-Hypervisor Communication Block (GHCB) using the VMGEXIT instruction.
The GHCB format and the protocol for using it is documented in "SEV-ES
Guest-Hypervisor Communication Block Standardization" [2].

The main areas of the EDK2 code that are updated to support SEV-ES are
around the exception handling support and the AP boot support.

Exception support is required starting in Sec, continuing through Pei
and into Dxe in order to handle #VC exceptions that are generated.
Each AP requires it's own GHCB page as well as a page to hold values
specific to that AP.

AP booting poses some interesting challenges. The INIT-SIPI-SIPI
sequence is typically used to boot the APs. However, the hypervisor is
not allowed to update the guest registers. The GHCB document [2] talks
about how SMP booting under SEV-ES is performed.

Since the GHCB page must be a shared (unencrypted) page, the processor
must be running in long mode in order for the guest and hypervisor to
communicate with each other. As a result, SEV-ES is only supported
under the X64 architecture.

This series adds a new library requirement for the VmgExitLib library
against the UefiCpuPkg CpuExceptionHandlerLib library and the
UefiCpuPkg MpInitLib library. The edk2-platforms repo requires
updates/patches to add the new library requirement. To accomodate
that, this series could be split between:

patch number 10:
UefiPayloadPkg: Prepare UefiPayloadPkg to use the VmgExitLib library

and patch number 11:
UefiCpuPkg/CpuExceptionHandler: Add base support for the #VC
exception

The updates to edk2-platforms can be applied at the split.

[1] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.amd.com%2Fsystem%2Ffiles%2FTechDocs%2F24593.pdf&;data=02%7C01%7Cthomas.lendacky%40amd.com%7C9f8ac7054fe14b45410108d842cf75d6%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637332807380740132&amp;sdata=2%2BQLHjbgwrn8p0ac7MCq17nwSZ%2BqEEadZk9yhTDUlPg%3D&amp;reserved=0
[2] https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdeveloper.amd.com%2Fwp-content%2Fresources%2F56421.pdf&;data=02%7C01%7Cthomas.lendacky%40amd.com%7C9f8ac7054fe14b45410108d842cf75d6%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637332807380740132&amp;sdata=mz43rsp%2F9py2d5eWmimrC9HilcF8pnbEKhkbJzJ%2BP40%3D&amp;reserved=0

---

These patches are based on commit:
65904cdbb33c ("UefiCpuPkg/MtrrLibUnitTest: Change to use static array
for CI test")

A version of the tree can be found at:
https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAMDESE%2Fovmf%2Ftree%2Fsev-es-v24&;data=02%7C01%7Cthomas.lendacky%40amd.com%7C9f8ac7054fe14b45410108d842cf75d6%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637332807380740132&amp;sdata=JglZJ9Ts5ZmFLLYQYb1iIBcY1HWXh6UosOh%2BtSjFm5Q%3D&amp;reserved=0

Cc: Andrew Fish <afish@apple.com>
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Benjamin You <benjamin.you@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien@xen.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ray Ni <ray.ni@intel.com>

Changes since v14:
- Address ECC errors
- Fix non-boolean comparison to use a comparison operator
- Separate declaration and initialization of variables
- Add period to first line of block comments
- Split single-line multiple declaration into multiple lines
The changes look good to me, thanks!

In this particular case, the updates do not invalidate my "Regression-tested-by" given under v14:

https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F63921&;data=02%7C01%7Cthomas.lendacky%40amd.com%7C9f8ac7054fe14b45410108d842cf75d6%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637332807380740132&amp;sdata=0ZQ3oULPfbBeSX5cvOfkGjCS4si%2FH2cqnkceyQcrUdY%3D&amp;reserved=0

"""
For all patches except #10 ("UefiPayloadPkg: Prepare UefiPayloadPkg to use the VmgExitLib library") and #46 ("Maintainers.txt: Add reviewers for the OvmfPkg SEV-related files"):

Regression-tested-by: Laszlo Ersek <lersek@redhat.com> """

So whoever merges this series should please apply that to the respective patches.

[Liming] Got it. This patch set has passed all review. I will help merge it for this stable tag stable202008.

Thanks!
Laszlo




Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand

Maciej Rabeda
 

Hi Vladimir,

I cannot apply the patch via 'git am'.
Is your git configured in a manner described here?
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo's-unkempt-git-guide-for-edk2-contributors-and-maintainers

Laszlo,

Were you able to apply this patch from .eml file?

Thanks,
Maciej

On 17-Aug-20 17:46, Vladimir Olovyannikov wrote:
Hi Gao,

Thanks for reviewing.
As you suggest, I will postpone the next patchset submission until
NetworkPkg maintainer(s) review.

-----Original Message-----
From: Gao, Zhichao <zhichao.gao@intel.com>
Sent: Sunday, August 16, 2020 6:48 PM
To: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>;
devel@edk2.groups.io
Cc: Laszlo Ersek <lersek@redhat.com>; Samer El-Haj-Mahmoud <Samer.El-
Haj-Mahmoud@arm.com>; Maciej Rabeda
<maciej.rabeda@linux.intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Fu,
Siyuan <siyuan.fu@intel.com>; Ni, Ray <ray.ni@intel.com>; Gao, Liming
<liming.gao@intel.com>; Nd <nd@arm.com>
Subject: RE: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand

Sorry for the delay reply.

See below:

-----Original Message-----
From: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
Sent: Tuesday, July 28, 2020 12:49 AM
To: devel@edk2.groups.io
Cc: Laszlo Ersek <lersek@redhat.com>; Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>; Samer El-Haj-Mahmoud
<Samer.El-
Haj-Mahmoud@arm.com>; Gao, Zhichao <zhichao.gao@intel.com>; Maciej
Rabeda <maciej.rabeda@linux.intel.com>; Wu, Jiaxin
<jiaxin.wu@intel.com>; Fu,
Siyuan <siyuan.fu@intel.com>; Ni, Ray <ray.ni@intel.com>; Gao, Liming
<liming.gao@intel.com>; Nd <nd@arm.com>
Subject: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand
Introduce an http client utilizing EDK2 HTTP protocol, to
allow fast image downloading from http/https servers.
HTTP download speed is usually faster than tftp.
The client is based on the same approach as tftp dynamic command, and
uses the same UEFI Shell command line parameters. This makes it easy
integrating http into existing UEFI Shell scripts.
Note that to enable HTTP download, feature Pcd
gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections must
be set to TRUE.
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2860

Signed-off-by: Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>
CC: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
CC: Laszlo Ersek <lersek@redhat.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Nd <nd@arm.com>
---
CryptoPkg/Library/OpensslLib/openssl | 2 +-
.../DynamicCommand/HttpDynamicCommand/Http.c | 1715
+++++++++++++++++
.../DynamicCommand/HttpDynamicCommand/Http.h | 89 +
.../HttpDynamicCommand/Http.uni | 117 ++
.../HttpDynamicCommand/HttpApp.c | 53 +
.../HttpDynamicCommand/HttpApp.inf | 58 +
.../HttpDynamicCommand/HttpDynamicCommand.c | 134 ++
.../HttpDynamicCommand/HttpDynamicCommand.inf | 63 +
ShellPkg/Include/Guid/ShellLibHiiGuid.h | 5 +
ShellPkg/ShellPkg.dec | 1 +
ShellPkg/ShellPkg.dsc | 5 +
11 files changed, 2241 insertions(+), 1 deletion(-)
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.inf
diff --git a/CryptoPkg/Library/OpensslLib/openssl
b/CryptoPkg/Library/OpensslLib/openssl
index e2e09d9fba11..c3656cc594da 160000
--- a/CryptoPkg/Library/OpensslLib/openssl
+++ b/CryptoPkg/Library/OpensslLib/openssl
@@ -1 +1 @@
-Subproject commit e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72
+Subproject commit c3656cc594daac8167721dde7220f0e59ae146fc
diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
new file mode 100644
index 000000000000..0565b07c3570
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
@@ -0,0 +1,1715 @@
+/** @file

+ The implementation for the 'http' Shell command.

+

+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved. <BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include "Http.h"

+

+#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32

+EFI_HII_HANDLE mHttpHiiHandle;

+

+/*

+ Constant strings and definitions related to the message

+ indicating the amount of progress in the dowloading of a HTTP
file.
+*/

+

+// Number of steps in the progression slider

+#define HTTP_PROGRESS_SLIDER_STEPS \

+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)

+

+// Size in number of characters plus one (final zero) of the message
to
+// indicate the progress of an HTTP download. The format is
"[(progress
slider:
+// 40 characters)] (nb of KBytes downloaded so far: 7 characters)
Kb".
There
+// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11
characters

+// (2 // spaces, "Kb" and seven characters for the number of KBytes).

+#define HTTP_PROGRESS_MESSAGE_SIZE \

+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)

+

+//

+// Buffer size. Note that larger buffer does not mean better speed!

+//

+#define DEFAULT_BUF_SIZE SIZE_32KB

+#define MAX_BUF_SIZE SIZE_4MB

+

+#define MIN_PARAM_COUNT 2

+#define MAX_PARAM_COUNT 4

+

+#define TIMER_MAX_TIMEOUT_S 10

+

+// File name to use when URI ends with "/"

+#define DEFAULT_HTML_FILE L"index.html"

+#define DEFAULT_HTTP_PROTO L"http"

+

+// String to delete the HTTP progress message to be able to update it
:
+// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b'

+#define HTTP_PROGRESS_DEL \

+
L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\
b\b\b\
+\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"

+

+#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b"

+// Frame for the progression slider

+#define HTTP_PROGR_FRAME L"[
]"
+

+// String descriptions for server errors

+STATIC CONST CHAR16 *ErrStatusDesc[] =

+{

+ L"400 Bad Request",

+ L"401 Unauthorized",

+ L"402 Payment required",

+ L"403 Forbidden",

+ L"404 Not Found",

+ L"405 Method not allowed",

+ L"406 Not acceptable",

+ L"407 Proxy authentication required",

+ L"408 Request time out",

+ L"409 Conflict",

+ L"410 Gone",

+ L"411 Length required",

+ L"412 Precondition failed",

+ L"413 Request entity too large",

+ L"414 Request URI to large",

+ L"415 Unsupported media type",

+ L"416 Requested range not satisfied",

+ L"417 Expectation failed",

+ L"500 Internal server error",

+ L"501 Not implemented",

+ L"502 Bad gateway",

+ L"503 Service unavailable",

+ L"504 Gateway timeout",

+ L"505 HTTP version not supported"

+};

+

+// Local File Handle

+STATIC SHELL_FILE_HANDLE mFileHandle = NULL;

+

+// Path of the local file, Unicode encoded

+STATIC CONST CHAR16 *mLocalFilePath;

+

+STATIC BOOLEAN gRequestCallbackComplete = FALSE;

+STATIC BOOLEAN gResponseCallbackComplete = FALSE;

+

+STATIC BOOLEAN gHttpError;

+

+/**

+ Cleans off leading and trailing spaces and tabs.

+

+ @param[in] String pointer to the string to trim them off.

+**/

+STATIC

+EFI_STATUS

+TrimSpaces (

+ IN CHAR16 **String

+ )

+{

+ ASSERT(String != NULL);

+ ASSERT(*String!= NULL);

+ //

+ // Remove any spaces and tabs at the beginning of the (*String).

+ //

+ while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {

+ CopyMem (

+ (*String),

+ (*String) + 1,

+ StrSize ((*String)) - sizeof((*String)[0])

+ );

+ }

+

+ //

+ // Remove any spaces and tabs at the end of the (*String).

+ //

+ while ((StrLen (*String) > 0) &&

+ (((*String)[StrLen ((*String)) - 1] == L' ') ||

+ ((*String)[StrLen ((*String)) - 1] == L'\t'))

+ ) {

+ (*String)[StrLen ((*String)) - 1] = CHAR_NULL;

+ }

+

+ return (EFI_SUCCESS);

+}

+

+

+/*

+ * Callbacks for request and response.

+ * We just acknowledge that operation has completed here.

+ */

+STATIC

+VOID

+EFIAPI

+RequestCallback (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+)

+{

+ gRequestCallbackComplete = TRUE;

+}

+

+STATIC

+VOID

+EFIAPI

+ResponseCallback (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+)

+{

+ gResponseCallbackComplete = TRUE;

+}

+

+

+/**

+ Check and convert the UINT16 option values of the 'http' command

+

+ @param[in] ValueStr Value as an Unicode encoded string

+ @param[out] Value UINT16 value

+

+ @return TRUE The value was returned.

+ @return FALSE A parsing error occured.

+**/

+STATIC

+BOOLEAN

+StringToUint16 (

+ IN CONST CHAR16 *ValueStr,

+ OUT UINT16 *Value

+ );

+

+/**

+ Get the name of the NIC.

+

+ @param[in] ControllerHandle The network physical device handle.

+ @param[in] NicNumber The network physical device number.

+ @param[out] NicName Address where to store the NIC name.

+ The memory area has to be at least

+
IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.

+

+ @return EFI_SUCCESS The name of the NIC was returned.

+ @return Others The creation of the child for the Managed

+ Network Service failed or the opening of

+ the Managed Network Protocol failed or

+ the operational parameters for the

+ Managed Network Protocol could not be

+ read.

+**/

+STATIC

+EFI_STATUS

+GetNicName (

+ IN EFI_HANDLE ControllerHandle,

+ IN UINTN NicNumber,

+ OUT CHAR16 *NicName

+ );

+

+/**

+ Create a child for the service identified by its service binding
protocol
GUID
+ and get from the child the interface of the protocol identified by
its
GUID.
+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the
+ service to be created.

+ @param[in] ProtocolGuid GUID of the protocol to be
open.
+ @param[out] ChildHandle Address where the handler
of the
+ created child is returned.
NULL is
+ returned in case of error.

+ @param[out] Interface Address where a pointer to
the
+ protocol interface is
returned in
+ case of success.

+

+ @return EFI_SUCCESS The child was created and the protocol
opened.
+ @return Others Either the creation of the child or the
opening
+ of the protocol failed.

+**/

+STATIC

+EFI_STATUS

+CreateServiceChildAndOpenProtocol (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ OUT EFI_HANDLE *ChildHandle,

+ OUT VOID **Interface

+ );

+

+/**

+ Close the protocol identified by its GUID on the child handle of
the
service
+ identified by its service binding protocol GUID, then destroy the
child
+ handle.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the
+ service to be destroyed.

+ @param[in] ProtocolGuid GUID of the protocol to be
closed.
+ @param[in] ChildHandle Handle of the child to be
destroyed.
+

+**/

+STATIC

+VOID

+CloseProtocolAndDestroyServiceChild (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ IN EFI_HANDLE ChildHandle

+ );

+

+

+/**

+ Worker function that download the data of a file from an HTTP
server
given
+ the path of the file and its size.

+

+ @param[in] Context A pointer to the download context.

+

+ @retval EFI_SUCCESS The file was downloaded.

+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.

+ @retval Others The downloading of the file

+ from the server failed.

+

+**/

+STATIC

+EFI_STATUS

+DownloadFile (

+ IN DOWNLOAD_CONTEXT *Context

+ );

+

+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {

+ {L"-i", TypeValue},

+ {L"-k", TypeFlag},

+ {L"-l", TypeValue},

+ {L"-s", TypeValue},

+ {L"-t", TypeValue},

+ {NULL , TypeMax}

+ };

+

+/**

+ Function for 'http' command.

+

+ @param[in] ImageHandle Handle to the Image (NULL if Internal).

+ @param[in] SystemTable Pointer to the System Table (NULL if
Internal).
+

+ @return SHELL_SUCCESS The 'http' command completed
successfully.
+ @return SHELL_ABORTED The Shell Library initialization
failed.
+ @return SHELL_INVALID_PARAMETER At least one of the command's
arguments is

+ not valid.

+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.

+ @return SHELL_NOT_FOUND Network Interface Card not found.

+ @return SHELL_UNSUPPORTED Command was valid, but the server
returned

+ a status code indicating some
error.
+ Examine the file requested for
error body.
+

+**/

+SHELL_STATUS

+RunHttp (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ LIST_ENTRY *CheckPackage;

+ UINTN ParamCount;

+ UINTN HandleCount;

+ UINTN NicNumber;

+ UINTN InitialSize;

+ UINTN ParamOffset;

+ UINTN StartSize;

+ CHAR16 *ProblemParam;

+ CHAR16
NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
+ CHAR16 *Walker1;

+ CHAR16 *VStr;

+ CONST CHAR16 *UserNicName;

+ CONST CHAR16 *ValueStr;

+ CONST CHAR16 *RemoteFilePath;

+ CONST CHAR16 *Walker;

+ EFI_HTTP_CONFIG_DATA HttpConfigData;

+ EFI_HTTPv4_ACCESS_POINT IPv4Node;

+ EFI_HANDLE *Handles;

+ EFI_HANDLE ControllerHandle;

+ EFI_HANDLE HttpChildHandle;

+ DOWNLOAD_CONTEXT Context;

+ BOOLEAN NicFound;

+

+ ProblemParam = NULL;

+ RemoteFilePath = NULL;

+ NicFound = FALSE;

+ Handles = NULL;

+

+ //

+ // Initialize the Shell library (we must be in non-auto-init...)

+ //

+ ParamOffset = 0;

+ gHttpError = FALSE;

+

+ Status = ShellInitialize ();

+ if (EFI_ERROR (Status)) {

+ ASSERT_EFI_ERROR (Status);

+ return SHELL_ABORTED;

+ }

+

+ ZeroMem (&Context, sizeof (Context));

+

+ //

+ // Parse the command line.

+ //

+ Status = ShellCommandLineParse (

+ ParamList,

+ &CheckPackage,

+ &ProblemParam,

+ TRUE);
I prefer to put ');' in next line like other functions.

+ if (EFI_ERROR (Status)) {

+ if ((Status == EFI_VOLUME_CORRUPTED) &&

+ (ProblemParam != NULL) ) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mHttpHiiHandle,

+ HTTP_APP_NAME, ProblemParam

+ );

+ SHELL_FREE_NON_NULL (ProblemParam);

+ } else {

+ ASSERT (FALSE);

+ }

+

+ goto Error;

+ }

+

+ //

+ // Check the number of parameters

+ //

+ Status = EFI_INVALID_PARAMETER;

+

+ ParamCount = ShellCommandLineGetCount (CheckPackage);

+ if (ParamCount > MAX_PARAM_COUNT) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),

+ mHttpHiiHandle, HTTP_APP_NAME

+ );

+ goto Error;

+ }

+

+ if (ParamCount < MIN_PARAM_COUNT) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),

+ mHttpHiiHandle, HTTP_APP_NAME

+ );

+ goto Error;

+ }

+

+ ZeroMem (&HttpConfigData, sizeof (HttpConfigData));

+ ZeroMem (&IPv4Node, sizeof (IPv4Node));

+ IPv4Node.UseDefaultAddress = TRUE;

+

+ HttpConfigData.HttpVersion = HttpVersion11;

+ HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;

+

+ //

+ // Get the host address (not necessarily IPv4 format)

+ //

+ ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+ if (!ValueStr) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
mHttpHiiHandle,
+ HTTP_APP_NAME, ValueStr

+ );

+ goto Error;

+ } else {

+ StartSize = 0;

+ if (!StrStr (ValueStr, L"://")) {

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ DEFAULT_HTTP_PROTO,

+ StrLen (DEFAULT_HTTP_PROTO)

+ );

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ L"://",

+ StrLen (L"://")

+ );

+ VStr = (CHAR16 *)ValueStr;

+ } else {

+ VStr = StrStr (ValueStr, L"://") + StrLen (L"://");

+ }

+

+ for (Walker1 = VStr; *Walker1; Walker1++) {

+ if (*Walker1 == L'/') {

+ break;

+ }

+ }

+

+ if (*Walker1 == L'/') {

+ ParamOffset = 1;

+ RemoteFilePath = Walker1;

+ }

+

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ ValueStr,

+ StrLen (ValueStr) - StrLen
(Walker1)
+ );

+ if (!Context.ServerAddrAndProto) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+ }

+

+ if (!RemoteFilePath) {

+ RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);

+ if (!RemoteFilePath) {

+ // If no path given, assume just "/"

+ RemoteFilePath = L"/";

+ }

+ }

+

+ TrimSpaces ((CHAR16 **)&RemoteFilePath);

+

+ if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {

+ mLocalFilePath = ShellCommandLineGetRawValue (

+ CheckPackage,

+ MAX_PARAM_COUNT - 1 - ParamOffset);

+ } else {

+ Walker = RemoteFilePath + StrLen (RemoteFilePath);

+ while ((--Walker) >= RemoteFilePath) {

+ if ((*Walker == L'\\') ||

+ (*Walker == L'/' ) ) {
It is better to remove the useless space in the above line at the end of
'if'
condition.

+ break;

+ }

+ }

+

+ mLocalFilePath = Walker + 1;

+ }

+

+ if (!StrLen (mLocalFilePath)) {

+ mLocalFilePath = DEFAULT_HTML_FILE;

+ }

+

+ InitialSize = 0;

+ Context.URI = StrnCatGrow (

+ &Context.URI,

+ &InitialSize,

+ RemoteFilePath,

+ StrLen (RemoteFilePath)

+ );

+ if (!Context.URI) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ //

+ // Get the name of the Network Interface Card to be used if any.

+ //

+ UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");

+ if (ValueStr != NULL) {

+ if (!StringToUint16 (

+ ValueStr,

+ &HttpConfigData.AccessPoint.IPv4Node->LocalPort

+ )

+ ) {
I suggest to align the end ')' of StringToUint16 to align with the
parameters.
And the end ')' of 'if' to go right next to the end ')' of
StringToUint16.
OK, will do.
+ goto Error;

+ }

+ }

+

+ Context.BufferSize = DEFAULT_BUF_SIZE;

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");

+ if (ValueStr != NULL) {

+ Context.BufferSize = ShellStrToUintn (ValueStr);

+ if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),

+ mHttpHiiHandle, HTTP_APP_NAME, ValueStr

+ );

+ goto Error;

+ }

+ }

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");

+ if (ValueStr != NULL) {

+ HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn
(ValueStr);
I am not sure if it is fine to transfer '-1' as time out value when the
-t with
invalid number string. It depends on the NetworkPkg maintainers' review.

I am OK with other part of the patch. But I still need NetworkPkg
maintainers'
help to review above issue and the implementation.
There is no need to resend another patch if NetworkPkg maintainers are
OK
with above issue and the implementation.
OK, I will postpone submission of the patch until NetworkPkg
maintainter(s) review.
Thanks,
Zhichao
Thank you,
Vladimir
+ }

+

+ //

+ // Locate all HTTP Service Binding protocols

+ //

+ Status = gBS->LocateHandleBuffer (

+ ByProtocol,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ NULL,

+ &HandleCount,

+ &Handles

+ );

+ if (EFI_ERROR (Status) || (HandleCount == 0)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NO_NIC),
mHttpHiiHandle
+ );

+ if (!EFI_ERROR (Status)) {

+ Status = EFI_NOT_FOUND;

+ }

+

+ goto Error;

+ }

+

+ Status = EFI_NOT_FOUND;

+

+ for (NicNumber = 0;

+ (NicNumber < HandleCount) && (Status != EFI_SUCCESS);

+ NicNumber++) {

+ ControllerHandle = Handles[NicNumber];

+

+ Status = GetNicName (ControllerHandle, NicNumber, NicName);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NAME),

+ mHttpHiiHandle, NicNumber, Status

+ );

+ continue;

+ }

+

+ if (UserNicName != NULL) {

+ if (StrCmp (NicName, UserNicName) != 0) {

+ Status = EFI_NOT_FOUND;

+ continue;

+ }

+ NicFound = TRUE;

+ }

+

+ Status = CreateServiceChildAndOpenProtocol (

+ ControllerHandle,

+ &gEfiHttpServiceBindingProtocolGuid,

+ &gEfiHttpProtocolGuid,

+ &HttpChildHandle,

+ (VOID**)&Context.Http

+ );

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL),

+ mHttpHiiHandle, NicName, Status

+ );

+ continue;

+ }

+

+ Status = Context.Http->Configure (Context.Http, &HttpConfigData);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_CONFIGURE),

+ mHttpHiiHandle, NicName, Status

+ );

+ continue;

+ }

+

+ Context.Flags = 0;

+ if (ShellCommandLineGetFlag (CheckPackage, L"-m")) {

+ Context.Flags |= DL_FLAG_TIME;

+ }

+

+ if (ShellCommandLineGetFlag (CheckPackage, L"-k")) {

+ Context.Flags |= DL_FLAG_KEEP_BAD;

+ }

+

+ Status = DownloadFile (&Context);

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle

+ );

+

+ CloseProtocolAndDestroyServiceChild (

+ ControllerHandle,

+ &gEfiHttpServiceBindingProtocolGuid,

+ &gEfiHttpProtocolGuid,

+ HttpChildHandle

+ );

+

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),

+ mHttpHiiHandle, RemoteFilePath, NicName, Status

+ );

+ // If a user aborted the operation, do not try another
controller.
+ if (Status == EFI_ABORTED) {

+ goto Error;

+ }

+ }

+

+ if (gHttpError) {

+ //

+ // This is not related to connection, so no need to repeat with

+ // another interface.

+ //

+ break;

+ }

+ }

+

+ if ((UserNicName != NULL) && (!NicFound)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND),

+ mHttpHiiHandle, UserNicName

+ );

+ }

+

+Error:

+ ShellCommandLineFreeVarList (CheckPackage);

+ SHELL_FREE_NON_NULL (Handles);

+ SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);

+ SHELL_FREE_NON_NULL (Context.URI);

+

+ return Status & ~MAX_BIT;

+}

+

+/**

+ Check and convert the UINT16 option values of the 'http' command

+

+ @param[in] ValueStr Value as an Unicode encoded string

+ @param[out] Value UINT16 value

+

+ @return TRUE The value was returned.

+ @return FALSE A parsing error occured.

+**/

+STATIC

+BOOLEAN

+StringToUint16 (

+ IN CONST CHAR16 *ValueStr,

+ OUT UINT16 *Value

+ )

+{

+ UINTN Val;

+

+ Val = ShellStrToUintn (ValueStr);

+ if (Val > MAX_UINT16) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),

+ mHttpHiiHandle, HTTP_APP_NAME, ValueStr

+ );

+ return FALSE;

+ }

+

+ *Value = (UINT16)Val;

+ return TRUE;

+}

+

+/**

+ Get the name of the NIC.

+

+ @param[in] ControllerHandle The network physical device handle.

+ @param[in] NicNumber The network physical device number.

+ @param[out] NicName Address where to store the NIC name.

+ The memory area has to be at least

+
IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.

+

+ @return EFI_SUCCESS The name of the NIC was returned.

+ @return Others The creation of the child for the Managed

+ Network Service failed or the opening of

+ the Managed Network Protocol failed or

+ the operational parameters for the

+ Managed Network Protocol could not be

+ read.

+**/

+STATIC

+EFI_STATUS

+GetNicName (

+ IN EFI_HANDLE ControllerHandle,

+ IN UINTN NicNumber,

+ OUT CHAR16 *NicName

+ )

+{

+ EFI_STATUS Status;

+ EFI_HANDLE MnpHandle;

+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;

+ EFI_SIMPLE_NETWORK_MODE SnpMode;

+

+ Status = CreateServiceChildAndOpenProtocol (

+ ControllerHandle,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ &gEfiManagedNetworkProtocolGuid,

+ &MnpHandle,

+ (VOID**)&Mnp

+ );

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);

+ if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {

+ goto Error;

+ }

+

+ UnicodeSPrint (

+ NicName,

+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,

+ SnpMode.IfType == NET_IFTYPE_ETHERNET ?

+ L"eth%d" :

+ L"unk%d",

+ NicNumber

+ );

+

+ Status = EFI_SUCCESS;

+

+Error:

+

+ if (MnpHandle != NULL) {

+ CloseProtocolAndDestroyServiceChild (

+ ControllerHandle,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ &gEfiManagedNetworkProtocolGuid,

+ MnpHandle

+ );

+ }

+

+ return Status;

+}

+

+/**

+ Create a child for the service identified by its service binding
protocol
GUID
+ and get from the child the interface of the protocol identified by
its
GUID.
+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the
+ service to be created.

+ @param[in] ProtocolGuid GUID of the protocol to be
open.
+ @param[out] ChildHandle Address where the handler
of the
+ created child is returned.
NULL is
+ returned in case of error.

+ @param[out] Interface Address where a pointer to
the
+ protocol interface is
returned in
+ case of success.

+

+ @return EFI_SUCCESS The child was created and the protocol
opened.
+ @return Others Either the creation of the child or the
opening
+ of the protocol failed.

+**/

+STATIC

+EFI_STATUS

+CreateServiceChildAndOpenProtocol (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ OUT EFI_HANDLE *ChildHandle,

+ OUT VOID **Interface

+ )

+{

+ EFI_STATUS Status;

+

+ *ChildHandle = NULL;

+ Status = NetLibCreateServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ ChildHandle

+ );

+ if (!EFI_ERROR (Status)) {

+ Status = gBS->OpenProtocol (

+ *ChildHandle,

+ ProtocolGuid,

+ Interface,

+ gImageHandle,

+ ControllerHandle,

+ EFI_OPEN_PROTOCOL_GET_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ NetLibDestroyServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ *ChildHandle

+ );

+ *ChildHandle = NULL;

+ }

+ }

+

+ return Status;

+}

+

+/**

+ Close the protocol identified by its GUID on the child handle of
the
service
+ identified by its service binding protocol GUID, then destroy the
child
+ handle.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the
+ service to be destroyed.

+ @param[in] ProtocolGuid GUID of the protocol to be
closed.
+ @param[in] ChildHandle Handle of the child to be
destroyed.
+

+**/

+STATIC

+VOID

+CloseProtocolAndDestroyServiceChild (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ IN EFI_HANDLE ChildHandle

+ )

+{

+ gBS->CloseProtocol (

+ ChildHandle,

+ ProtocolGuid,

+ gImageHandle,

+ ControllerHandle

+ );

+

+ NetLibDestroyServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ ChildHandle

+ );

+}

+

+/**

+ Wait until operation completes. Completion is indicated by

+ setting of an appropriate variable.

+

+ @param[in] Context A pointer to the HTTP download
context.
+ @param[in] CallBackComplete A pointer to the callback
completion
+ variable set by the callback.

+

+ @return EFI_SUCCESS Callback signalled completion.

+ @return EFI_TIMEOUT Timed out waiting for completion.

+ @return Others Error waiting for completion.

+**/

+STATIC

+EFI_STATUS

+WaitForCompletion (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN OUT BOOLEAN *CallBackComplete

+ )

+{

+ EFI_STATUS Status;

+ EFI_EVENT WaitEvt;

+

+ Status = EFI_SUCCESS;

+

+ // Use a timer to measure timeout. Cannot use Stall here!

+ Status = gBS->CreateEvent (

+ EVT_TIMER,

+ TPL_CALLBACK,

+ NULL,

+ NULL,

+ &WaitEvt

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ if (!EFI_ERROR (Status)) {

+ Status = gBS->SetTimer(

+ WaitEvt,

+ TimerRelative,

+ EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S)

+ );

+

+ ASSERT_EFI_ERROR (Status);

+ }

+

+ while (! *CallBackComplete &&

+ (!EFI_ERROR (Status)) &&

+ EFI_ERROR (gBS->CheckEvent (WaitEvt))

+ ) {

+ Status = Context->Http->Poll (Context->Http);

+ }

+

+ gBS->SetTimer (WaitEvt, TimerCancel, 0);

+ gBS->CloseEvent (WaitEvt);

+

+ if (*CallBackComplete) {

+ return EFI_SUCCESS;

+ }

+

+ if (!EFI_ERROR (Status)) {

+ Status = EFI_TIMEOUT;

+ }

+

+ return Status;

+}

+

+/**

+ Generate and send a request to the http server.

+

+ @param[in] Context HTTP download context.

+ @param[in] DownloadUrl Fully qualified URL to be
downloaded.
+

+ @return EFI_SUCCESS Request has been sent successfully.

+ @return EFI_INVALID_PARAMETER Invalid URL.

+ @return EFI_OUT_OF_RESOURCES Out of memory.

+ @return EFI_DEVICE_ERROR If HTTPS is used, this probably

+ means that TLS support either was
not
+ installed or not configured.

+ @return Others Error sending the request.

+**/

+

+STATIC

+EFI_STATUS

+SendRequest (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_HTTP_REQUEST_DATA RequestData;

+ EFI_HTTP_HEADER RequestHeader;

+ EFI_HTTP_MESSAGE RequestMessage;

+ EFI_STATUS Status;

+ CHAR16 *Host;

+ UINTN StringSize;

+

+ ZeroMem (&RequestData, sizeof (RequestData));

+ ZeroMem (&RequestHeader, sizeof (RequestHeader));

+ ZeroMem (&RequestMessage, sizeof (RequestMessage));

+ ZeroMem (&Context->RequestToken, sizeof (Context-
RequestToken));

+

+ RequestHeader.FieldName = "Host";

+

+ Host = (CHAR16 *)Context->ServerAddrAndProto;

+ while (*Host != CHAR_NULL && *Host != L'/') {

+ Host++;

+ }

+

+ if (*Host == CHAR_NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ //

+ // Get the next slash

+ //

+ Host++;

+ //

+ // And now the host name

+ //

+ Host++;

+

+ StringSize = StrLen (Host) + 1;

+ RequestHeader.FieldValue = AllocatePool (StringSize);

+ if (!RequestHeader.FieldValue) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ UnicodeStrToAsciiStrS (Host, RequestHeader.FieldValue,
StringSize);
+

+ RequestMessage.HeaderCount++;

+

+ RequestData.Method = HttpMethodGet;

+ RequestData.Url = DownloadUrl;

+

+ RequestMessage.Data.Request = &RequestData;

+ RequestMessage.Headers = &RequestHeader;

+ RequestMessage.BodyLength = 0;

+ RequestMessage.Body = NULL;

+ Context->RequestToken.Event = NULL;

+

+ //

+ // Completion callback event to be set when Request completes.

+ //

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ RequestCallback,

+ Context,

+ &Context->RequestToken.Event

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ Context->RequestToken.Status = EFI_SUCCESS;

+ Context->RequestToken.Message = &RequestMessage;

+ gRequestCallbackComplete = FALSE;

+ Status = Context->Http->Request (Context->Http, &Context-
RequestToken);

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ Status = WaitForCompletion (Context, &gRequestCallbackComplete);

+ if (EFI_ERROR (Status)) {

+ Context->Http->Cancel (Context->Http, &Context->RequestToken);

+ }

+Error:

+ SHELL_FREE_NON_NULL (RequestHeader.FieldValue);

+ if (Context->RequestToken.Event) {

+ gBS->CloseEvent (Context->RequestToken.Event);

+ ZeroMem (&Context->RequestToken, sizeof (Context-
RequestToken));

+ }

+

+ return Status;

+}

+

+/**

+ Update the progress of a file download

+ This procedure is called each time a new HTTP body portion is
received.
+

+ @param[in] Context HTTP download context.

+ @param[in] DownloadLen Portion size, in bytes.

+ @param[in] Buffer The pointer to the parsed buffer.

+

+ @retval EFI_SUCCESS Portion saved.

+ @retval Other Error saving the portion.

+

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+SavePortion (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN UINTN DownloadLen,

+ IN CHAR8 *Buffer

+ )

+{

+ CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE];

+ UINTN NbOfKb;

+ UINTN Index;

+ UINTN LastStep;

+ UINTN Step;

+ EFI_STATUS Status;

+

+ LastStep = 0;

+ Step = 0;

+ ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes);

+ Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer);

+ if (EFI_ERROR (Status)) {

+ if (Context->ContentDownloaded > 0) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle

+ );

+ }

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_WRITE),

+ mHttpHiiHandle, mLocalFilePath, Status

+ );

+

+ return Status;

+ }

+

+ if (Context->ContentDownloaded == 0) {

+ ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME);

+ }

+

+ Context->ContentDownloaded += DownloadLen;

+ NbOfKb = Context->ContentDownloaded >> 10;

+

+ Progress[0] = L'\0';

+ if (Context->ContentLength) {

+ LastStep = (Context->LastReportedNbOfBytes *
HTTP_PROGRESS_SLIDER_STEPS) /

+ Context->ContentLength;

+ Step = (Context->ContentDownloaded *
HTTP_PROGRESS_SLIDER_STEPS) /
+ Context->ContentLength;

+ }

+

+ Context->LastReportedNbOfBytes = Context->ContentDownloaded;

+

+ if (Step <= LastStep) {

+ if (!Context->ContentLength) {

+ //

+ // Update downloaded size, there is no length info available.

+ //

+ ShellPrintEx (-1, -1, L"%s", HTTP_KB);

+ ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb);

+ }

+

+ return EFI_SUCCESS;

+ }

+

+ ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL);

+

+ Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE,
HTTP_PROGR_FRAME);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ for (Index = 1; Index < Step; Index++) {

+ Progress[Index] = L'=';

+ }

+

+ if (Step) {

+ Progress[Step] = L'>';

+ }

+

+ UnicodeSPrint (

+ Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1,

+ sizeof (Progress) - sizeof (HTTP_PROGR_FRAME),

+ L" %7d Kb",

+ NbOfKb

+ );

+

+

+ ShellPrintEx (-1, -1, L"%s", Progress);

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Replace the original Host and URI with Host and URI returned by the

+ HTTP server in 'Location' header (redirection).

+

+ @param[in] Location A pointer to the 'Location' string

+ provided by HTTP server.

+ @param[in] Context A pointer to HTTP download context.

+ @param[in] DownloadUrl Fully qualified HTTP URL.

+

+ @return EFI_SUCCESS Host and URI were successfully set.

+ @return EFI_OUT_OF_RESOURCES Error setting Host or URI.

+**/

+

+STATIC

+EFI_STATUS

+SetHostURI (

+ IN CHAR8 *Location,

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_STATUS Status;

+ UINTN StringSize;

+ UINTN FirstStep;

+ UINTN Idx;

+ UINTN Step;

+ CHAR8 *Walker;

+ CHAR16 *Temp;

+ CHAR8 *Tmp;

+ CHAR16 *Url;

+ BOOLEAN IsAbEmptyUrl;

+

+ Tmp = NULL;

+ Url = NULL;

+ IsAbEmptyUrl = FALSE;

+ FirstStep = 0;

+

+ StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));

+ Url = AllocateZeroPool (StringSize);

+ if (!Url) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Location,

+ Url,

+ StringSize

+ );

+

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ //

+ // If an HTTP server redirects to the same location more than once,

+ // then stop attempts and tell it is not reachable.

+ //

+ if (!StrCmp (Url, DownloadUrl)) {

+ Status = EFI_NO_MAPPING;

+ goto Error;

+ }

+

+ if (AsciiStrLen (Location) > 2) {

+ // Some servers return 'Location: //server/resource'

+ IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');

+ if (IsAbEmptyUrl) {

+ // Skip first "//"

+ Location += 2;

+ FirstStep = 1;

+ }

+ }

+

+ if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {

+ Idx = 0;

+ Walker = Location;

+

+ for (Step = FirstStep; Step < 2; Step++) {

+ for (; *Walker != '/' && *Walker != '\0'; Walker++) {

+ Idx++;

+ }

+ if (!Step) {

+ //

+ // Skip "//"

+ //

+ Idx += 2;

+ Walker += 2;

+ }

+ }

+

+ Tmp = AllocateZeroPool (Idx + 1);

+ if (!Tmp) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ CopyMem (Tmp, Location, Idx);

+

+ //

+ // Location now points to URI

+ //

+ Location += Idx;

+ StringSize = (Idx + 1) * sizeof (CHAR16);

+

+ SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);

+

+ Temp = AllocateZeroPool (StringSize);

+ if (!Temp) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Tmp,

+ Temp,

+ StringSize

+ );

+ if (EFI_ERROR (Status)) {

+ SHELL_FREE_NON_NULL (Temp);

+ goto Error;

+ }

+

+ Idx = 0;

+ if (IsAbEmptyUrl) {

+ Context->ServerAddrAndProto = StrnCatGrow (

+ &Context->ServerAddrAndProto,

+ &Idx,

+ L"http://",

+ StrLen (L"http://")

+ );

+ }

+

+ Context->ServerAddrAndProto = StrnCatGrow (

+ &Context->ServerAddrAndProto,

+ &Idx,

+ Temp,

+ StrLen (Temp)

+ );

+ SHELL_FREE_NON_NULL (Temp);

+ if (!Context->ServerAddrAndProto) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+ }

+

+ SHELL_FREE_NON_NULL (Context->URI);

+

+ StringSize = AsciiStrSize (Location) * sizeof (CHAR16);

+ Context->URI = AllocateZeroPool (StringSize);

+ if (!Context->URI) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ //

+ // Now make changes to the URI part.

+ //

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Location,

+ Context->URI,

+ StringSize

+ );

+Error:

+ SHELL_FREE_NON_NULL (Tmp);

+ SHELL_FREE_NON_NULL (Url);

+ return Status;

+}

+

+/**

+ Message parser callback.

+ Save a portion of HTTP body.

+

+ @param[in] EventType Type of event. Can be either

+ OnComplete or OnData.

+ @param[in] Data A pointer to the buffer with data.

+ @param[in] Length Data length of this portion.

+ @param[in] Context A pointer to the HTTP download
context.
+

+ @return EFI_SUCCESS The portion was processed successfully.

+ @return Other Error returned by SavePortion.

+**/

+

+STATIC

+EFI_STATUS

+EFIAPI

+ParseMsg (

+ IN HTTP_BODY_PARSE_EVENT EventType,

+ IN CHAR8 *Data,

+ IN UINTN Length,

+ IN VOID *Context

+ )

+{

+ if (!Data || (EventType == BodyParseEventOnComplete) || !Context) {

+ return EFI_SUCCESS;

+ }

+

+ return SavePortion (Context, Length, Data);

+}

+

+

+/**

+ Get HTTP server response and collect the whole body as a file.

+ Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR).

+ Note that even if HTTP server returns an error code, it might send

+ the body as well. This body will be collected in the resultant
file.
+

+ @param[in] Context A pointer to the HTTP download
context.
+ @param[in] DownloadedUrl A pointer to the fully qualified URL
to
download.
+

+ @return EFI_SUCCESS Valid file. Body successfully
collected.
+ @return EFI_HTTP_ERROR Response is a valid HTTP response, but
the
+ HTTP server

+ indicated an error (HTTP code >= 400).

+ Response body MAY contain full

+ HTTP server response.

+ @return Others Error getting the reponse from the
HTTP server.
+ Response body is not collected.

+**/

+STATIC

+EFI_STATUS

+GetResponse (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_HTTP_RESPONSE_DATA ResponseData;

+ EFI_HTTP_MESSAGE ResponseMessage;

+ EFI_HTTP_HEADER *Header;

+ EFI_STATUS Status;

+ VOID *MsgParser;

+ CONST CHAR16 *Desc;

+ BOOLEAN IsTrunked;

+ BOOLEAN Redirection;

+

+ ZeroMem (&ResponseData, sizeof (ResponseData));

+ ZeroMem (&ResponseMessage, sizeof (ResponseMessage));

+ ZeroMem (&Context->ResponseToken, sizeof (Context-
ResponseToken));

+ IsTrunked = FALSE;

+

+ ResponseMessage.Body = Context->Buffer;

+ Context->ResponseToken.Status = EFI_SUCCESS;

+ Context->ResponseToken.Message = &ResponseMessage;

+ Context->ContentLength = 0;

+ Context->Status = REQ_OK;

+ MsgParser = NULL;

+ ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;

+ ResponseMessage.Data.Response = &ResponseData;

+ Context->ResponseToken.Event = NULL;

+

+ do {

+ SHELL_FREE_NON_NULL (ResponseMessage.Headers);

+ ResponseMessage.HeaderCount = 0;

+ gResponseCallbackComplete = FALSE;

+ ResponseMessage.BodyLength = Context->BufferSize;

+

+ if (ShellGetExecutionBreakFlag ()) {

+ Status = EFI_ABORTED;

+ break;

+ }

+

+ if (!Context->ContentDownloaded && !Context-
ResponseToken.Event) {

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ ResponseCallback,

+ Context,

+ &Context->ResponseToken.Event

+ );

+ ASSERT_EFI_ERROR (Status);

+ } else {

+ ResponseMessage.Data.Response = NULL;

+ }

+

+ if (EFI_ERROR (Status)) {

+ break;

+ }

+

+ Status = Context->Http->Response (Context->Http, &Context-
ResponseToken);
+ if (EFI_ERROR (Status)) {

+ break;

+ }

+

+ Status = WaitForCompletion (Context, &gResponseCallbackComplete);

+ if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {

+ Status = EFI_SUCCESS;

+ }

+

+ if (EFI_ERROR (Status)) {

+ Context->Http->Cancel (Context->Http, &Context->ResponseToken);

+ break;

+ }

+

+ if (!Context->ContentDownloaded) {

+ Redirection =

+ ((ResponseData.StatusCode >=
HTTP_STATUS_300_MULTIPLE_CHOICES)
&&

+ (ResponseData.StatusCode <=
HTTP_STATUS_307_TEMPORARY_REDIRECT)

+ ) ||

+ (ResponseData.StatusCode ==
HTTP_STATUS_308_PERMANENT_REDIRECT);

+

+ if (Redirection) {

+ //

+ // Need to repeat the request with new Location (server
redirected).
+ //

+ Context->Status = REQ_NEED_REPEAT;

+

+ Header = HttpFindHeader (

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ "Location"

+ );

+ if (Header) {

+ Status = SetHostURI (Header->FieldValue, Context,
DownloadUrl);
+ if (Status == EFI_NO_MAPPING) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),

+ mHttpHiiHandle, Context->ServerAddrAndProto,

+ L"Recursive HTTP server relocation",

+ Context->URI

+ );

+ }

+ } else {

+ //

+ // Bad reply from the server. Server must specify the
location.
+ // Indicate that resource was not found, and no body
collected.
+ //

+ Status = EFI_NOT_FOUND;

+ }

+

+ Context->Http->Cancel (Context->Http,
&Context->ResponseToken);
+ break;

+ }

+

+ //

+ // Init message-body parser by header information.

+ //

+ if (!MsgParser) {

+ Status = HttpInitMsgParser (

+ ResponseMessage.Data.Request->Method,

+ ResponseData.StatusCode,

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ ParseMsg,

+ Context,

+ &MsgParser

+ );

+ if (EFI_ERROR (Status)) {

+ break;

+ }

+ }

+

+ //

+ // If it is a trunked message, rely on the parser.

+ //

+ Header = HttpFindHeader (

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ "Transfer-Encoding"

+ );

+ IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue,
"chunked"));
+

+ HttpGetEntityLength (MsgParser, &Context->ContentLength);

+

+ if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST
&&
+ (ResponseData.StatusCode !=
HTTP_STATUS_308_PERMANENT_REDIRECT)

+ ) {

+ //

+ // Server reported an error via Response code.

+ // Collect the body if any.

+ //

+ if (!gHttpError) {

+ gHttpError = TRUE;

+

+ Desc = ErrStatusDesc[ResponseData.StatusCode -

+ HTTP_STATUS_400_BAD_REQUEST];

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),

+ mHttpHiiHandle, Context->ServerAddrAndProto,

+ Desc,

+ Context->URI

+ );

+

+ //

+ // This gives an RFC HTTP error.

+ //

+ Context->Status = ShellStrToUintn (Desc);

+ }

+ }

+ }

+

+ // Do NOT try to parse an empty body.

+ if (ResponseMessage.BodyLength || IsTrunked) {

+ Status = HttpParseMessageBody (

+ MsgParser,

+ ResponseMessage.BodyLength,

+ ResponseMessage.Body

+ );

+ }

+ } while (!HttpIsMessageComplete (MsgParser) &&

+ !EFI_ERROR (Status) &&

+ ResponseMessage.BodyLength

+ );

+

+ SHELL_FREE_NON_NULL (MsgParser);

+ if (Context->ResponseToken.Event) {

+ gBS->CloseEvent (Context->ResponseToken.Event);

+ ZeroMem (&Context->ResponseToken, sizeof (Context-
ResponseToken));

+ }

+

+ return Status;

+}

+

+/**

+ Worker function that downloads the data of a file from an HTTP
server
given
+ the path of the file and its size.

+

+ @param[in] Context A pointer to the HTTP download
context.
+

+ @retval EFI_SUCCESS The file was downloaded.

+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.

+ #retval EFI_HTTP_ERROR The server returned a valid HTTP
error.
+ Examine the mLocalFilePath file

+ to get error body.

+ @retval Others The downloading of the file from the
server
+ failed.

+

+**/

+STATIC

+EFI_STATUS

+DownloadFile (

+ IN DOWNLOAD_CONTEXT *Context

+ )

+{

+ EFI_STATUS Status;

+ CHAR16 *DownloadUrl;

+ UINTN UrlSize;

+

+ ASSERT (Context);

+ if (!Context) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ DownloadUrl = NULL;

+

+ Context->Buffer = AllocatePool (Context->BufferSize);

+ if (!Context->Buffer) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto ON_EXIT;

+ }

+

+ //

+ // OPEN FILE

+ //

+ if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {

+ ShellDeleteFileByName (mLocalFilePath);

+ }

+

+ Status = ShellOpenFileByName (

+ mLocalFilePath,

+ &mFileHandle,

+ EFI_FILE_MODE_CREATE |

+ EFI_FILE_MODE_WRITE |

+ EFI_FILE_MODE_READ,

+ 0);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),

+ mHttpHiiHandle, HTTP_APP_NAME, mLocalFilePath

+ );

+ goto ON_EXIT;

+ }

+

+ do {

+ SHELL_FREE_NON_NULL (DownloadUrl);

+ UrlSize = 0;

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ Context->ServerAddrAndProto,

+ StrLen (Context->ServerAddrAndProto)

+ );

+ if (Context->URI[0] != L'/') {

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ L"/",

+ StrLen (Context->ServerAddrAndProto)

+ );

+ }

+

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ Context->URI,

+ StrLen (Context->URI));

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_DOWNLOADING),

+ mHttpHiiHandle, DownloadUrl);

+

+ Status = SendRequest (Context, DownloadUrl);

+ if (Status) {

+ goto ON_EXIT;

+ }

+

+ Status = GetResponse (Context, DownloadUrl);

+

+ if (Status) {

+ goto ON_EXIT;

+ }

+

+ } while (Context->Status == REQ_NEED_REPEAT);

+

+ if (Context->Status) {

+ Status = ENCODE_ERROR (Context->Status);

+ }

+

+ON_EXIT:

+ //

+ // CLOSE FILE

+ //

+ if (mFileHandle) {

+ if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) {

+ ShellDeleteFile (&mFileHandle);

+ } else {

+ ShellCloseFile (&mFileHandle);

+ }

+ }

+

+ SHELL_FREE_NON_NULL (DownloadUrl);

+ SHELL_FREE_NON_NULL (Context->Buffer);

+

+ return Status;

+}

+

+/**

+ Retrive HII package list from ImageHandle and publish to HII
database.
+

+ @param ImageHandle The image handle of the process.

+

+ @return HII handle.

+**/

+EFI_HII_HANDLE

+InitializeHiiPackage (

+ EFI_HANDLE ImageHandle

+ )

+{

+ EFI_STATUS Status;

+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;

+ EFI_HII_HANDLE HiiHandle;

+

+ //

+ // Retrieve HII package list from ImageHandle

+ //

+ Status = gBS->OpenProtocol (

+ ImageHandle,

+ &gEfiHiiPackageListProtocolGuid,

+ (VOID **)&PackageList,

+ ImageHandle,

+ NULL,

+ EFI_OPEN_PROTOCOL_GET_PROTOCOL

+ );

+ ASSERT_EFI_ERROR (Status);

+ if (EFI_ERROR (Status)) {

+ return NULL;

+ }

+

+ //

+ // Publish HII package list to HII Database.

+ //

+ Status = gHiiDatabase->NewPackageList (

+ gHiiDatabase,

+ PackageList,

+ NULL,

+ &HiiHandle

+ );

+ ASSERT_EFI_ERROR (Status);

+ if (EFI_ERROR (Status)) {

+ return NULL;

+ }

+

+ return HiiHandle;

+}

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
new file mode 100644
index 000000000000..5c7b90e8cab4
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
@@ -0,0 +1,89 @@
+/** @file

+ Header file for 'http' command functions.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef _HTTP_H_

+#define _HTTP_H_

+

+#include <Uefi.h>

+

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DebugLib.h>

+#include <Library/HiiLib.h>

+#include <Library/HttpLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/NetLib.h>

+#include <Library/PrintLib.h>

+#include <Library/ShellLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiHiiServicesLib.h>

+#include <Library/UefiLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+

+#include <Protocol/HiiPackageList.h>

+#include <Protocol/HttpUtilities.h>

+#include <Protocol/ServiceBinding.h>

+

+#define HTTP_APP_NAME L"http"

+

+#define REQ_OK 0

+#define REQ_NEED_REPEAT 1

+

+// Download Flags

+#define DL_FLAG_TIME BIT0 // Show elapsed time.

+#define DL_FLAG_KEEP_BAD BIT1 // Keep files even if download failed.

+

+extern EFI_HII_HANDLE mHttpHiiHandle;

+

+typedef struct {

+ UINTN ContentDownloaded;

+ UINTN ContentLength;

+ UINTN LastReportedNbOfBytes;

+ UINTN BufferSize;

+ UINTN Status;

+ UINTN Flags;

+ UINT8 *Buffer;

+ CHAR16 *ServerAddrAndProto;

+ CHAR16 *URI;

+ EFI_HTTP_TOKEN ResponseToken;

+ EFI_HTTP_TOKEN RequestToken;

+ EFI_HTTP_PROTOCOL *Http;

+} DOWNLOAD_CONTEXT;

+

+/**

+ Function for 'http' command.

+

+ @param[in] ImageHandle The image handle.

+ @param[in] SystemTable The system table.

+

+ @retval SHELL_SUCCESS Command completed successfully.

+ @retval SHELL_INVALID_PARAMETER Command usage error.

+ @retval SHELL_ABORTED The user aborts the operation.

+ @retval value Unknown error.

+**/

+SHELL_STATUS

+RunHttp (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ );

+

+/**

+ Retrive HII package list from ImageHandle and publish to HII
database.
+

+ @param ImageHandle The image handle of the process.

+

+ @return HII handle.

+**/

+EFI_HII_HANDLE

+InitializeHiiPackage (

+ EFI_HANDLE ImageHandle

+ );

+#endif // _HTTP_H_

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
new file mode 100644
index 000000000000..00cf05deeb5c
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
@@ -0,0 +1,117 @@
+// /**

+//

+// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development
LP<BR>
+// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
<BR>
+// Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// Module Name:

+//

+// Http.uni

+//

+// Abstract:

+//

+// String definitions for UEFI Shell HTTP command

+//

+//

+// **/

+

+/=#

+

+#langdef en-US "english"

+

+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too
many
arguments. Try help http.\r\n"

+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few
arguments. Try help http.\r\n"

+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid
argument - '%H%s%N'. Try help http.\r\n"

+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown
flag -
'%H%s%N'. Try help http.\r\n"

+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot
open
file - '%H%s%N'\r\n"

+#string STR_GEN_CRLF #language en-US "\r\n"

+

+#string STR_HTTP_ERR_NO_NIC #language en-US "No network
interface
card found.\r\n"

+#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the
name
of the network interface card number %d - %r\r\n"

+#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to
open
HTTP protocol on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to
configure
HTTP protocol on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to
download
the file '%H%s%N' on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_WRITE #language en-US "Unable to write
into
file
'%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network
Interface
Card '%H%s%N' not found.\r\n"

+#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N'
reports
'%s' for '%H%s%N' \r\n"

+#string STR_HTTP_DOWNLOADING #language en-US "Downloading
'%H%s%N'\r\n"

+

+#string STR_GET_HELP_HTTP #language en-US ""

+".TH http 0 "Download a file from HTTP server."\r\n"

+".SH NAME\r\n"

+"Download a file from HTTP server.\r\n"

+".SH SYNOPSIS\r\n"

+" \r\n"

+"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n"

+" <URL> [localfilepath]\r\n"

+".SH OPTIONS\r\n"

+" \r\n"

+" -i interface - Specifies an adapter name, i.e., eth0.\r\n"

+" -k Keep the downloaded file even if there was an
error.\r\n"
+" If this parameter is not used, the file will be
deleted.\r\n"
+" -l port - Specifies the local port number. Default value
is 0\r\n"
+" and the port number is automatically
assigned.\r\n"
+" -m Measure and report download time (in seconds).
\r\n"
+" -s size The size of the download buffer for a chunk, in
bytes.\r\n"
+" Default is 32K. Note that larger buffer does
not imply\r\n"
+" better speed.\r\n"

+" -t timeout - The number of seconds to wait for completion
of\r\n"
+" requests and responses. Default is 0 which is
'automatic'.\r\n"
+" %HURL%N\r\n"

+" Two types of providing of URLs are supported:\r\n"

+" 1. tftp-like, where host and http_uri are separate
parameters\r\n"
+" (example: host /host_uri), and\r\n\"

+" 2. wget-like, where host and host_uri is one parameter.\r\n"

+" (example: host/host_uri)\r\n"

+"\r\n"

+" host - Specifies HTTP Server address.\r\n

+ Can be either IPv4 address or 'http (or
https)://addr'\r\n
+ Can use addresses resolvable by DNS as well.
\r\n
+ Port can be specified after ':' if needed.
\r\n
+ By default port 80 is used.\r\n"

+" http_uri - HTTP server URI to download the file.\r\n"

+"\r\n"

+" localfilepath - Local destination file path.\r\n"

+".SH DESCRIPTION\r\n"

+" \r\n"

+"NOTES:\r\n"

+" 1. The HTTP command allows geting of the file specified by its
'http_uri'\r\n"
+" path from the HTTP server specified by its 'host' IPv4 address.
If
the\r\n"
+" optional 'localfilepath' parameter is provided, the downloaded
file
is\r\n"
+" stored locally using the provided file path. If the local file
path is\r\n"
+" not specified, the file is stored in the current directory
using the
file\r\n"
+" server's name.\r\n"

+" 2. Before using the HTTP command, the network interface intended
to
be\r\n"

+" used to retrieve the file must be configured. This
configuration may
be\r\n"
+" done by means of the 'ifconfig' command.\r\n"

+" 3. If a network interface is defined with the '-i' option then
only
this\r\n"
+" interface will be used to retrieve the remote file. Otherwise,
all
network\r\n"

+" interfaces are tried in the order they have been discovered
during
the\r\n"
+" DXE phase.\r\n"

+".SH EXAMPLES\r\n"

+" \r\n"

+"EXAMPLES:\r\n"

+" * To get the file "dir1/file1.dat" from the HTTP server
192.168.1.1, port
8080,
and\r\n"

+" store it as file2.dat in the current directory (use tftp-like
URL format)
:\r\n"
+" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n"

+" * To get the file /image.bin via HTTPS from server 192.168.1.1 at
port 443
\r\n"

+" (default HTTPS port), and store it in the current directory:
\r\n"
+" fs0:\> http https://192.168.1.1 image.bin\r\n"

+" To get an index file from http://google.com and place it into
the \r\n"
+" current directory:\r\n"

+" fs0:\> http google.com index.html\r\n"

+".SH RETURNVALUES\r\n"

+" \r\n"

+"RETURN VALUES:\r\n"

+" SHELL_SUCCESS The action was completed as
requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was
incorrectly\r\n"

+" formatted or its value was out of
bounds.\r\n"
+" HTTP_ERROR No EFI errors, but the server reported a
status
code\r\n"

+" which should be treated as an error. If
an error body
sent\r\n"
+" by the server, and -k parameter is on
command line,
+" the file wil be saved either as
localfilepath filename,\r\n"
+" or as an URI name in the current
directory.\r\n"
+" If '/' is at the end of the URL, and no
locafilepath
filename\r\n"
+" is given on the command line, the file
will be retrieved
as\r\n"
+" index.html.\r\n"

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
new file mode 100644
index 000000000000..7bd5b46d3997
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
@@ -0,0 +1,53 @@
+/** @file

+ Entrypoint of "http" shell standalone application.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include "Http.h"

+

+/*

+ * String token ID of help message text.

+ * Shell supports to find help message in the resource section of an

+ * application image if * .MAN file is not found.

+ * This global variable is added to make build tool recognizes

+ * that the help string is consumed by user and then build tool will

+ * add the string into the resource section.

+ * Thus the application can use '-?' option to show help message in
Shell.
+ */

+GLOBAL_REMOVE_IF_UNREFERENCED

+EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN
(STR_GET_HELP_HTTP);
+

+/**

+ Entry point of Http standalone application.

+

+ @param ImageHandle The image handle of the process.

+ @param SystemTable The EFI System Table pointer.

+

+ @retval EFI_SUCCESS Http command is executed sucessfully.

+ @retval EFI_ABORTED HII package was failed to initialize.

+ @retval others Other errors when executing http
command.
+**/

+EFI_STATUS

+EFIAPI

+HttpAppInitialize (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);

+ if (mHttpHiiHandle == NULL) {

+ return EFI_ABORTED;

+ }

+

+ Status = (EFI_STATUS)RunHttp (ImageHandle, SystemTable);

+

+ HiiRemovePackages (mHttpHiiHandle);

+

+ return Status;

+}

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
new file mode 100644
index 000000000000..d08d47fb37d5
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
@@ -0,0 +1,58 @@
+## @file

+# Provides Shell 'http' standalone application.

+#

+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010006

+ BASE_NAME = http

+ FILE_GUID =
56B00FB7-91D2-869B-CE5C-26CD1A89C73C
+ MODULE_TYPE = UEFI_APPLICATION

+ VERSION_STRING = 1.0

+ ENTRY_POINT = HttpAppInitialize

+#

+# This flag specifies whether HII resource section is generated into
PE
image.
+#

+ UEFI_HII_RESOURCE_SECTION = TRUE

+

+[Sources.common]

+ Http.c

+ HttpApp.c

+ Http.h

+ Http.uni

+

+[Packages]

+ EmbeddedPkg/EmbeddedPkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ MdePkg/MdePkg.dec

+ NetworkPkg/NetworkPkg.dec

+ ShellPkg/ShellPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ BaseMemoryLib

+ DebugLib

+ FileHandleLib

+ HiiLib

+ HttpLib

+ MemoryAllocationLib

+ NetLib

+ ShellLib

+ UefiApplicationEntryPoint

+ UefiBootServicesTableLib

+ UefiHiiServicesLib

+ UefiLib

+ UefiRuntimeServicesTableLib

+

+[Protocols]

+ gEfiHiiPackageListProtocolGuid ## CONSUMES

+ gEfiHttpProtocolGuid ## CONSUMES

+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES

+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
new file mode 100644
index 000000000000..ba654749a075
--- /dev/null
+++
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
@@ -0,0 +1,134 @@
+/** @file

+ Produce "http" shell dynamic command.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include <Protocol/ShellDynamicCommand.h>

+#include "Http.h"

+

+/**

+ This is the shell command handler function pointer callback type.
This
+ function handles the command when it is invoked in the shell.

+

+ @param[in] This The instance of the

+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+ @param[in] SystemTable The pointer to the system table.

+ @param[in] ShellParameters The parameters associated with the
command.
+ @param[in] Shell The instance of the shell protocol
used in
+ the context of processing this
command.
+

+ @return EFI_SUCCESS the operation was sucessful

+ @return other the operation failed.

+**/

+SHELL_STATUS

+EFIAPI

+HttpCommandHandler (

+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,

+ IN EFI_SYSTEM_TABLE *SystemTable,

+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,

+ IN EFI_SHELL_PROTOCOL *Shell

+ )

+{

+ gEfiShellParametersProtocol = ShellParameters;

+ gEfiShellProtocol = Shell;

+

+ return RunHttp (gImageHandle, SystemTable);

+}

+

+/**

+ This is the command help handler function pointer callback type.
This
+ function is responsible for displaying help information for the
associated
+ command.

+

+ @param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+ @param[in] Language The pointer to the language string to use.

+

+ @return string Pool allocated help string, must be freed by
caller
+**/

+CHAR16 *

+EFIAPI

+HttpCommandGetHelp (

+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,

+ IN CONST CHAR8 *Language

+ )

+{

+ return HiiGetString(mHttpHiiHandle,

+ STRING_TOKEN (STR_GET_HELP_HTTP),

+ Language);

+}

+

+EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand
= {
+ HTTP_APP_NAME,

+ HttpCommandHandler,

+ HttpCommandGetHelp

+};

+

+/**

+ Entry point of Http Dynamic Command.

+

+ Produce the DynamicCommand protocol to handle "http" command.

+

+ @param ImageHandle The image handle of the process.

+ @param SystemTable The EFI System Table pointer.

+

+ @retval EFI_SUCCESS Http command is executed sucessfully.

+ @retval EFI_ABORTED HII package was failed to initialize.

+ @retval others Other errors when executing http
command.
+**/

+EFI_STATUS

+EFIAPI

+HttpCommandInitialize (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+

+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);

+ if (mHttpHiiHandle == NULL) {

+ return EFI_ABORTED;

+ }

+

+ Status = gBS->InstallProtocolInterface (

+ &ImageHandle,

+ &gEfiShellDynamicCommandProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &mHttpDynamicCommand

+ );

+ ASSERT_EFI_ERROR (Status);

+ return Status;

+}

+

+/**

+ Http driver unload handler.

+

+ @param ImageHandle The image handle of the process.

+

+ @retval EFI_SUCCESS The image is unloaded.

+ @retval Others Failed to unload the image.

+**/

+EFI_STATUS

+EFIAPI

+HttpUnload (

+ IN EFI_HANDLE ImageHandle

+)

+{

+ EFI_STATUS Status;

+ Status = gBS->UninstallProtocolInterface (

+ ImageHandle,

+ &gEfiShellDynamicCommandProtocolGuid,

+ &mHttpDynamicCommand

+ );

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ HiiRemovePackages (mHttpHiiHandle);

+

+ return EFI_SUCCESS;

+}

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
new file mode 100644
index 000000000000..5d46ee2384d5
--- /dev/null
+++
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
@@ -0,0 +1,63 @@
+## @file

+# Provides Shell 'http' dynamic command.

+#

+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010006

+ BASE_NAME = httpDynamicCommand

+ FILE_GUID =
19618BCE-55AE-09C6-37E9-4CE04084C7A1
+ MODULE_TYPE = DXE_DRIVER

+ VERSION_STRING = 1.0

+ ENTRY_POINT = HttpCommandInitialize

+ UNLOAD_IMAGE = HttpUnload

+#

+# This flag specifies whether HII resource section is generated into
PE
image.
+#

+ UEFI_HII_RESOURCE_SECTION = TRUE

+

+[Sources.common]

+ Http.c

+ HttpDynamicCommand.c

+ Http.h

+ Http.uni

+

+[Packages]

+ EmbeddedPkg/EmbeddedPkg.dec

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ NetworkPkg/NetworkPkg.dec

+ ShellPkg/ShellPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ BaseMemoryLib

+ DebugLib

+ FileHandleLib

+ HiiLib

+ HttpLib

+ MemoryAllocationLib

+ NetLib

+ ShellLib

+ UefiBootServicesTableLib

+ UefiDriverEntryPoint

+ UefiHiiServicesLib

+ UefiLib

+ UefiRuntimeServicesTableLib

+

+[Protocols]

+ gEfiHiiPackageListProtocolGuid ## CONSUMES

+ gEfiHttpProtocolGuid ## CONSUMES

+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES

+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES

+ gEfiShellDynamicCommandProtocolGuid ## PRODUCES

+

+[DEPEX]

+ TRUE

diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index 5da9128333a4..6e328b460d8c 100644
--- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -59,6 +59,10 @@
0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2,
0x0e,
0xd4 }
\

}



+#define SHELL_HTTP_HII_GUID \

+ { \

+ 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e,
0x0a,
0x7e } \

+ }



#define SHELL_BCFG_HII_GUID \

{ \

@@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;

extern EFI_GUID gShellNetwork2HiiGuid;

extern EFI_GUID gShellTftpHiiGuid;

+extern EFI_GUID gShellHttpHiiGuid;

extern EFI_GUID gShellBcfgHiiGuid;



#endif

diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
index d0843d338126..7b2d1230bd2c 100644
--- a/ShellPkg/ShellPkg.dec
+++ b/ShellPkg/ShellPkg.dec
@@ -53,6 +53,7 @@ [Guids]
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8,
{0xb0, 0xb7,
0xfa,
0x99, 0x9c, 0x62, 0x37, 0xae}}

gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12,
{0xaa, 0x60,
0x59,
0xdf, 0xf8, 0xd6, 0xea, 0x37}}

gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592,
{0x8f, 0xf7, 0xc1,
0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}

+ gShellHttpHiiGuid = {0x390f84b3, 0x221c, 0x4d9e,
{0xb5, 0x06,
0x6d,
0xb9, 0x42, 0x3e, 0x0a, 0x7e}}

gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d,
{0xa6, 0xb2, 0xeb,
0x12, 0xda, 0xb4, 0xa2, 0xb6}}

gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc,
{0xb5, 0xef,
0x2e,
0xf5, 0x5e, 0x24, 0x93, 0x2a}}

# FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf

diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 86e9f1e0040d..c42bc9464a0f 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -139,6 +139,11 @@ [Components]
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

}

ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf

+
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.inf {
+ <PcdsFixedAtBuild>

+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

+ }

+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf

ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
{
<PcdsFixedAtBuild>

gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

--
2.26.2.266.ge870325ee8


Re: [PATCH 0/2] BaseTools: Python 3.9 fixes

Laszlo Ersek
 

On 08/11/20 19:28, Cole wrote:
These patches fix two issues running the BaseTools test suite
on python 3.9 from Fedora rawhide. See patches for individual details

Cole Robinson (2):
BaseTools: fix ucs-2 lookup on python 3.9
BaseTools: Work around array.array.tostring() removal in python 3.9

BaseTools/Source/Python/AutoGen/UniClassObject.py | 2 +-
BaseTools/Source/Python/Common/Misc.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
Thank you, Cole, for the patches! The series has been merged in commit
range 5dc2699d101d..43bec9ea3d56.

Laszlo


Re: [PATCH v15 00/46] SEV-ES guest support

Laszlo Ersek
 

On 08/17/20 06:09, Gao, Liming wrote:
This patch set have been merged edk2 7f7f511c5a74676523ed48435350f6e35282b62b..7f0b28415cb464832155d5b3ff6eb63612f58645
Thank you!
Laszlo

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Liming Gao
Sent: 2020年8月14日 9:20
To: Laszlo Ersek <lersek@redhat.com>; Tom Lendacky <thomas.lendacky@amd.com>; devel@edk2.groups.io
Cc: Brijesh Singh <brijesh.singh@amd.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Ni, Ray <ray.ni@intel.com>; Andrew Fish <afish@apple.com>; Anthony Perard <anthony.perard@citrix.com>; You, Benjamin <benjamin.you@intel.com>; Bi, Dandan <dandan.bi@intel.com>; Dong, Guo <guo.dong@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Julien Grall <julien@xen.org>; Leif Lindholm <leif@nuviainc.com>; Ma, Maurice <maurice.ma@intel.com>
Subject: Re: [edk2-devel] [PATCH v15 00/46] SEV-ES guest support

Laszlo:

-----Original Message-----
From: Laszlo Ersek <lersek@redhat.com>
Sent: 2020年8月14日 3:54
To: Tom Lendacky <thomas.lendacky@amd.com>; devel@edk2.groups.io
Cc: Brijesh Singh <brijesh.singh@amd.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Dong, Eric <eric.dong@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Ni, Ray <ray.ni@intel.com>; Andrew Fish <afish@apple.com>; Anthony Perard <anthony.perard@citrix.com>; You, Benjamin <benjamin.you@intel.com>; Bi, Dandan <dandan.bi@intel.com>; Dong, Guo <guo.dong@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Julien Grall <julien@xen.org>; Leif Lindholm <leif@nuviainc.com>; Ma, Maurice <maurice.ma@intel.com>
Subject: Re: [PATCH v15 00/46] SEV-ES guest support

On 08/13/20 15:22, Tom Lendacky wrote:
From: Tom Lendacky <thomas.lendacky@amd.com>

This patch series provides support for running EDK2/OVMF under SEV-ES.

Secure Encrypted Virtualization - Encrypted State (SEV-ES) expands on
the SEV support to protect the guest register state from the
hypervisor. See
"AMD64 Architecture Programmer's Manual Volume 2: System Programming",
section "15.35 Encrypted State (SEV-ES)" [1].

In order to allow a hypervisor to perform functions on behalf of a
guest, there is architectural support for notifying a guest's
operating system when certain types of VMEXITs are about to occur.
This allows the guest to selectively share information with the
hypervisor to satisfy the requested function. The notification is
performed using a new exception, the VMM Communication exception
(#VC). The information is shared through the Guest-Hypervisor Communication Block (GHCB) using the VMGEXIT instruction.
The GHCB format and the protocol for using it is documented in "SEV-ES
Guest-Hypervisor Communication Block Standardization" [2].

The main areas of the EDK2 code that are updated to support SEV-ES are
around the exception handling support and the AP boot support.

Exception support is required starting in Sec, continuing through Pei
and into Dxe in order to handle #VC exceptions that are generated.
Each AP requires it's own GHCB page as well as a page to hold values
specific to that AP.

AP booting poses some interesting challenges. The INIT-SIPI-SIPI
sequence is typically used to boot the APs. However, the hypervisor is
not allowed to update the guest registers. The GHCB document [2] talks
about how SMP booting under SEV-ES is performed.

Since the GHCB page must be a shared (unencrypted) page, the processor
must be running in long mode in order for the guest and hypervisor to
communicate with each other. As a result, SEV-ES is only supported
under the X64 architecture.

This series adds a new library requirement for the VmgExitLib library
against the UefiCpuPkg CpuExceptionHandlerLib library and the
UefiCpuPkg MpInitLib library. The edk2-platforms repo requires
updates/patches to add the new library requirement. To accomodate
that, this series could be split between:

patch number 10:
UefiPayloadPkg: Prepare UefiPayloadPkg to use the VmgExitLib library

and patch number 11:
UefiCpuPkg/CpuExceptionHandler: Add base support for the #VC
exception

The updates to edk2-platforms can be applied at the split.

[1] https://www.amd.com/system/files/TechDocs/24593.pdf
[2] https://developer.amd.com/wp-content/resources/56421.pdf

---

These patches are based on commit:
65904cdbb33c ("UefiCpuPkg/MtrrLibUnitTest: Change to use static array
for CI test")

A version of the tree can be found at:
https://github.com/AMDESE/ovmf/tree/sev-es-v24

Cc: Andrew Fish <afish@apple.com>
Cc: Anthony Perard <anthony.perard@citrix.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Benjamin You <benjamin.you@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Julien Grall <julien@xen.org>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ray Ni <ray.ni@intel.com>

Changes since v14:
- Address ECC errors
- Fix non-boolean comparison to use a comparison operator
- Separate declaration and initialization of variables
- Add period to first line of block comments
- Split single-line multiple declaration into multiple lines
The changes look good to me, thanks!

In this particular case, the updates do not invalidate my "Regression-tested-by" given under v14:

https://edk2.groups.io/g/devel/message/63921

"""
For all patches except #10 ("UefiPayloadPkg: Prepare UefiPayloadPkg to use the VmgExitLib library") and #46 ("Maintainers.txt: Add reviewers for the OvmfPkg SEV-related files"):

Regression-tested-by: Laszlo Ersek <lersek@redhat.com> """

So whoever merges this series should please apply that to the respective patches.

[Liming] Got it. This patch set has passed all review. I will help merge it for this stable tag stable202008.

Thanks!
Laszlo




Re: [PATCH EDK2 v2 1/1] SecurityPkg/DxeImageVerificationLib:Enhanced verification of Offset

Laszlo Ersek
 

Hi Jiewen,

On 08/14/20 10:53, Yao, Jiewen wrote:
To Jiewen,
Sorry, I don't have environment to reproduce the issue.
Please help me understand, if you don’t have environment to reproduce the issue, how do you guarantee that your patch does fix the problem and we don’t have any other vulnerabilities?
The original bug report in
<https://bugzilla.tianocore.org/show_bug.cgi?id=2215#c0> is seriously
lacking. It does not go into detail about the alleged integer overflow.
It does not quote the code, does not explain the control flow, does not
identify the exact edk2 commit at which the vulnerability exists.

The bug report also does not offer a reproducer.

Additionally, the exact statement that the bug report does make, namely

it's possible to overflow Offset back to 0 causing an endless loop

is wrong (as far as I can tell anyway). It is not "OffSet" that can be
overflowed to zero, but the *addend* that is added to OffSet can be
overflowed to zero. Therefore the infinite loop will arise because
OffSet remains stuck at its present value, and not because OffSet will
be re-set to zero.

For the reasons, we can only speculate as to what the actual problem is,
unless Jian decides to join the discussion and clarifies what he had in
mind originally.

My understanding (or even "reconstruction") of the vulnerability is
described above, and in the patches that I proposed.

We can write a patch based on code analysis. It's possible to identify
integer overflows based on code analysis, and it's possible to verify
the correctness of fixes by code review. Obviously testing is always
good, but many times, constructing reproducers for such issues that were
found by code review, is difficult and time consuming. We can say that
we don't fix vulnerabilities without reproducers, or we can say that we
make an effort to fix them even if all we have is code analysis (and not
a reproducer).

So the above paragraph concerns "correctness". Regarding "completeness",
I guarantee you that this patch does not fix *all* problems related to
PE parsing. (See the other BZ tickets.) It does fix *one* issue with PE
parsing. We can say that we try to fix such issues gradually (give
different CVE numbers to different issues, and address them one at a
time), or we can say that we rewrite PE parsing from the ground up.
(BTW: I have seriously attempted that in the past, and I gave up,
because the PE format is FUBAR.)

In summary:

- the problem statement is unclear,

- it seems like there is indeed an integer overflow problem in the
SecDataDir parsing loop, but it's uncertain whether the bug reporter had
exactly that in mind

- PE parsing is guaranteed to have other vulnerabilities elsewhere in
edk2, but I'm currently unaware of other such issues in
DxeImageVerificationLib specifically

- even if there are other such problems (in DxeImageVerificationLib or
elswehere), fixing this bug that we know about is likely worthwhile

- for many such bugs, constructing a reproducer is difficult and time
consuming; code analysis, and *regression-testing* are frequently the
only tools we have. That doesn't mean we should ignore this class of bugs.

(Fixing integer overflows retro-actively is more difficult than writing
overflow-free code in the first place, but that ship has sailed; so we
can only fight these bugs incrementally now, unless we can rewrite PE
parsing with a new data structure from the ground up. Again I tried that
and gave up, because the spec is not public, and what I did manage to
learn about PE, showed that it was insanely over-engineered. I'm not
saying that other binary / executable formats are better, of course.)

Please check out my patches (inlined elsewhere in this thread), and
comment whether you'd like me to post them to the list as a standalone
series.

Jian: it wouldn't hurt if you commented as well.

Thanks
Laszlo

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of wenyi,xie
via groups.io
Sent: Friday, August 14, 2020 3:54 PM
To: Laszlo Ersek <lersek@redhat.com>; devel@edk2.groups.io; Yao, Jiewen
<jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>
Cc: huangming23@huawei.com; songdongkuang@huawei.com
Subject: Re: [edk2-devel] [PATCH EDK2 v2 1/1]
SecurityPkg/DxeImageVerificationLib:Enhanced verification of Offset

To Laszlo,
Thank you for your detailed description, I agree with what you analyzed and I'm
OK with your patches, it's
correct and much simpler.

To Jiewen,
Sorry, I don't have environment to reproduce the issue.

Thanks
Wenyi

On 2020/8/14 2:50, Laszlo Ersek wrote:
On 08/13/20 13:55, Wenyi Xie wrote:
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2215

There is an integer overflow vulnerability in DxeImageVerificationHandler
function when parsing the PE files attribute certificate table. In cases
where WinCertificate->dwLength is sufficiently large, it's possible to
overflow Offset back to 0 causing an endless loop.

Check offset inbetween VirtualAddress and VirtualAddress + Size.
Using SafeintLib to do offset addition with result check.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Wenyi Xie <xiewenyi2@huawei.com>
---
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf |
1 +
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h |
1 +
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c |
111 +++++++++++---------
3 files changed, 63 insertions(+), 50 deletions(-)

diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
index 1e1a639857e0..a7ac4830b3d4 100644
---
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
@@ -53,6 +53,7 @@ [LibraryClasses]
SecurityManagementLib
PeCoffLib
TpmMeasurementLib
+ SafeIntLib

[Protocols]
gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES
diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
index 17955ff9774c..060273917d5d 100644
---
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.h
@@ -23,6 +23,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DevicePathLib.h>
#include <Library/SecurityManagementLib.h>
#include <Library/PeCoffLib.h>
+#include <Library/SafeIntLib.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/DevicePath.h>
#include <Protocol/BlockIo.h>
diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index 36b87e16d53d..dbc03e28c05b 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -1658,6 +1658,10 @@ DxeImageVerificationHandler (
EFI_STATUS HashStatus;
EFI_STATUS DbStatus;
BOOLEAN IsFound;
+ UINT32 AlignedLength;
+ UINT32 Result;
+ EFI_STATUS AddStatus;
+ BOOLEAN IsAuthDataAssigned;

SignatureList = NULL;
SignatureListSize = 0;
@@ -1667,6 +1671,7 @@ DxeImageVerificationHandler (
Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
IsVerified = FALSE;
IsFound = FALSE;
+ Result = 0;

//
// Check the image type and get policy setting.
@@ -1850,9 +1855,10 @@ DxeImageVerificationHandler (
// The first certificate starts at offset (SecDataDir->VirtualAddress) from the
start of the file.
//
for (OffSet = SecDataDir->VirtualAddress;
- OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
- OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate-
dwLength))) {
+ (OffSet >= SecDataDir->VirtualAddress) && (OffSet < (SecDataDir-
VirtualAddress + SecDataDir->Size));) {
+ IsAuthDataAssigned = FALSE;
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
+ AlignedLength = WinCertificate->dwLength + ALIGN_SIZE (WinCertificate-
dwLength);

I disagree with this patch.

The primary reason for my disagreement is that the bug report
<https://bugzilla.tianocore.org/show_bug.cgi?id=2215#c0> is inexact, and
so this patch tries to fix the wrong thing.

With edk2 master at commit 65904cdbb33c, it is *not* possible to
overflow the OffSet variable to zero with "WinCertificate->dwLength"
*purely*, and cause an endless loop. Note that we have (at commit
65904cdbb33c):

for (OffSet = SecDataDir->VirtualAddress;
OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate-
dwLength))) {
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof
(WIN_CERTIFICATE) ||
(SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate-
dwLength) {
break;
}

The last sub-condition checks whether the Security Data Directory has
enough room left for "WinCertificate->dwLength". If not, then we break
out of the loop.

If we *do* have enough room, that is:

(SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) >= WinCertificate-
dwLength

then we have (by adding OffSet to both sides):

SecDataDir->VirtualAddress + SecDataDir->Size >= OffSet + WinCertificate-
dwLength

The left hand side is a known-good UINT32, and so incrementing OffSet (a
UINT32) *solely* by "WinCertificate->dwLength" (also a UINT32) does not
cause an overflow.

Instead, the problem is with the alignment. The "if" statement checks
whether we have enough room for "dwLength", but then "OffSet" is
advanced by "dwLength" *aligned up* to the next multiple of 8. And that
may indeed cause various overflows.

Now, the main problem with the present patch is that it does not fix one
of those overflows. Namely, consider that "dwLength" is very close to
MAX_UINT32 (or even think it's exactly MAX_UINT32). Then aligning it up
to the next multiple of 8 will yield 0. In other words, "AlignedLength"
will be zero.

And when that happens, there's going to be an infinite loop just the
same: "OffSet" will not be zero, but it will be *stuck*. The
SafeUint32Add() call at the bottom will succeed, but it will not change
the value of "OffSet".

More at the bottom.


if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof
(WIN_CERTIFICATE) ||
(SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <
WinCertificate->dwLength) {
break;
@@ -1872,6 +1878,8 @@ DxeImageVerificationHandler (
}
AuthData = PkcsCertData->CertData;
AuthDataSize = PkcsCertData->Hdr.dwLength - sizeof(PkcsCertData->Hdr);
+ IsAuthDataAssigned = TRUE;
+ HashStatus = HashPeImageByType (AuthData, AuthDataSize);
} else if (WinCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID)
{
//
// The certificate is formatted as WIN_CERTIFICATE_UEFI_GUID which is
described in UEFI Spec.
@@ -1880,72 +1888,75 @@ DxeImageVerificationHandler (
if (WinCertUefiGuid->Hdr.dwLength <=
OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) {
break;
}
- if (!CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
- continue;
+ if (CompareGuid (&WinCertUefiGuid->CertType, &gEfiCertPkcs7Guid)) {
+ AuthData = WinCertUefiGuid->CertData;
+ AuthDataSize = WinCertUefiGuid->Hdr.dwLength -
OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
+ IsAuthDataAssigned = TRUE;
+ HashStatus = HashPeImageByType (AuthData, AuthDataSize);
}
- AuthData = WinCertUefiGuid->CertData;
- AuthDataSize = WinCertUefiGuid->Hdr.dwLength -
OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
} else {
if (WinCertificate->dwLength < sizeof (WIN_CERTIFICATE)) {
break;
}
- continue;
}

- HashStatus = HashPeImageByType (AuthData, AuthDataSize);
- if (EFI_ERROR (HashStatus)) {
- continue;
- }
-
- //
- // Check the digital signature against the revoked certificate in forbidden
database (dbx).
- //
- if (IsForbiddenByDbx (AuthData, AuthDataSize)) {
- Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
- IsVerified = FALSE;
- break;
- }
-
- //
- // Check the digital signature against the valid certificate in allowed
database (db).
- //
- if (!IsVerified) {
- if (IsAllowedByDb (AuthData, AuthDataSize)) {
- IsVerified = TRUE;
+ if (IsAuthDataAssigned && !EFI_ERROR (HashStatus)) {
+ //
+ // Check the digital signature against the revoked certificate in forbidden
database (dbx).
+ //
+ if (IsForbiddenByDbx (AuthData, AuthDataSize)) {
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;
+ IsVerified = FALSE;
+ break;
}
- }

- //
- // Check the image's hash value.
- //
- DbStatus = IsSignatureFoundInDatabase (
- EFI_IMAGE_SECURITY_DATABASE1,
- mImageDigest,
- &mCertType,
- mImageDigestSize,
- &IsFound
- );
- if (EFI_ERROR (DbStatus) || IsFound) {
- Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
- DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s
hash of image is found in DBX.\n", mHashTypeStr));
- IsVerified = FALSE;
- break;
- }
+ //
+ // Check the digital signature against the valid certificate in allowed
database (db).
+ //
+ if (!IsVerified) {
+ if (IsAllowedByDb (AuthData, AuthDataSize)) {
+ IsVerified = TRUE;
+ }
+ }

- if (!IsVerified) {
+ //
+ // Check the image's hash value.
+ //
DbStatus = IsSignatureFoundInDatabase (
- EFI_IMAGE_SECURITY_DATABASE,
+ EFI_IMAGE_SECURITY_DATABASE1,
mImageDigest,
&mCertType,
mImageDigestSize,
&IsFound
);
- if (!EFI_ERROR (DbStatus) && IsFound) {
- IsVerified = TRUE;
- } else {
- DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but
signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n",
mHashTypeStr));
+ if (EFI_ERROR (DbStatus) || IsFound) {
+ Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed
but %s hash of image is found in DBX.\n", mHashTypeStr));
+ IsVerified = FALSE;
+ break;
}
+
+ if (!IsVerified) {
+ DbStatus = IsSignatureFoundInDatabase (
+ EFI_IMAGE_SECURITY_DATABASE,
+ mImageDigest,
+ &mCertType,
+ mImageDigestSize,
+ &IsFound
+ );
+ if (!EFI_ERROR (DbStatus) && IsFound) {
+ IsVerified = TRUE;
+ } else {
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but
signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n",
mHashTypeStr));
+ }
+ }
+ }
+
+ AddStatus = SafeUint32Add (OffSet, AlignedLength, &Result);
+ if (EFI_ERROR (AddStatus)) {
+ break;
}
+ OffSet = Result;
}

if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
There are other (smaller) reasons why I dislike this patch:

- The "IsAuthDataAssigned" variable is superfluous; we could use the
existent "AuthData" variable (with a NULL-check and a NULL-assignment)
similarly.

- The patch complicates / reorganizes the control flow needlessly. This
complication originates from placing the checked "OffSet" increment at
the bottom of the loop, which then requires the removal of all the
"continue" statements. But we don't need to check-and-increment at the
bottom. We can keep the increment inside the "for" statement, only
extend the *existent* room check (which I've quoted) to take the
alignment into account as well. If there is enough room for the
alignment in the security data directory, then that guarantees there
won't be a UINT32 overflow either.

All in all, I'm proposing the following three patches instead. The first
two patches are preparation, the last patch is the fix.

Patch#1:

From 11af0a104d34d39bf1b1aab256428ae4edbddd77 Mon Sep 17 00:00:00
2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 13 Aug 2020 19:11:39 +0200
Subject: [PATCH 1/3] SecurityPkg/DxeImageVerificationLib: extract
SecDataDirEnd, SecDataDirLeft

The following two quantities:

SecDataDir->VirtualAddress + SecDataDir->Size
SecDataDir->VirtualAddress + SecDataDir->Size - OffSet

are used multiple times in DxeImageVerificationHandler(). Introduce helper
variables for them: "SecDataDirEnd" and "SecDataDirLeft", respectively.
This saves us multiple calculations and significantly simplifies the code.

Note that all three summands above have type UINT32, therefore the new
variables are also of type UINT32.

This patch does not change behavior.

(Note that the code already handles the case when the

SecDataDir->VirtualAddress + SecDataDir->Size

UINT32 addition overflows -- namely, in that case, the certificate loop is
never entered, and the corruption check right after the loop fires.)

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c | 12
++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index 36b87e16d53d..8761980c88aa 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -1652,6 +1652,8 @@ DxeImageVerificationHandler (
UINT8 *AuthData;
UINTN AuthDataSize;
EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
+ UINT32 SecDataDirEnd;
+ UINT32 SecDataDirLeft;
UINT32 OffSet;
CHAR16 *NameStr;
RETURN_STATUS PeCoffStatus;
@@ -1849,12 +1851,14 @@ DxeImageVerificationHandler (
// "Attribute Certificate Table".
// The first certificate starts at offset (SecDataDir->VirtualAddress) from the
start of the file.
//
+ SecDataDirEnd = SecDataDir->VirtualAddress + SecDataDir->Size;
for (OffSet = SecDataDir->VirtualAddress;
- OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
+ OffSet < SecDataDirEnd;
OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate-
dwLength))) {
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
- if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof
(WIN_CERTIFICATE) ||
- (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <
WinCertificate->dwLength) {
+ SecDataDirLeft = SecDataDirEnd - OffSet;
+ if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE) ||
+ SecDataDirLeft < WinCertificate->dwLength) {
break;
}

@@ -1948,7 +1952,7 @@ DxeImageVerificationHandler (
}
}

- if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
+ if (OffSet != SecDataDirEnd) {
//
// The Size in Certificate Table or the attribute certificate table is corrupted.
//
--
2.19.1.3.g30247aa5d201
Patch#2:

From 72012c065a53582f7df695e7b9730c45f49226c6 Mon Sep 17 00:00:00
2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 13 Aug 2020 19:19:06 +0200
Subject: [PATCH 2/3] SecurityPkg/DxeImageVerificationLib: assign
WinCertificate after size check

Currently the (SecDataDirLeft <= sizeof (WIN_CERTIFICATE)) check only
guards the de-referencing of the "WinCertificate" pointer. It does not
guard the calculation of hte pointer itself:

WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);

This is wrong; if we don't know for sure that we have enough room for a
WIN_CERTIFICATE, then even creating such a pointer, not just
de-referencing it, may invoke undefined behavior.

Move the pointer calculation after the size check.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c | 8
+++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index 8761980c88aa..461ed7cfb5ac 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -1855,10 +1855,12 @@ DxeImageVerificationHandler (
for (OffSet = SecDataDir->VirtualAddress;
OffSet < SecDataDirEnd;
OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate-
dwLength))) {
- WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
SecDataDirLeft = SecDataDirEnd - OffSet;
- if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE) ||
- SecDataDirLeft < WinCertificate->dwLength) {
+ if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE)) {
+ break;
+ }
+ WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
+ if (SecDataDirLeft < WinCertificate->dwLength) {
break;
}

--
2.19.1.3.g30247aa5d201
Patch#3:

From 0bbba15b84f8f9f2cdc770a89f418aaec6cfb31e Mon Sep 17 00:00:00
2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Thu, 13 Aug 2020 19:34:33 +0200
Subject: [PATCH 3/3] SecurityPkg/DxeImageVerificationLib: catch alignment
overflow (CVE-2019-14562)

The DxeImageVerificationHandler() function currently checks whether
"SecDataDir" has enough room for "WinCertificate->dwLength". However,
for
advancing "OffSet", "WinCertificate->dwLength" is aligned to the next
multiple of 8. If "WinCertificate->dwLength" is large enough, the
alignment will return 0, and "OffSet" will be stuck at the same value.

Check whether "SecDataDir" has room left for both
"WinCertificate->dwLength" and the alignment.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c | 4
+++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git
a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index 461ed7cfb5ac..e38eb981b7a0 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++
b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -1860,7 +1860,9 @@ DxeImageVerificationHandler (
break;
}
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
- if (SecDataDirLeft < WinCertificate->dwLength) {
+ if (SecDataDirLeft < WinCertificate->dwLength ||
+ (SecDataDirLeft - WinCertificate->dwLength <
+ ALIGN_SIZE (WinCertificate->dwLength))) {
break;
}

--
2.19.1.3.g30247aa5d201
If Wenyi and the reviewers are OK with these patches, I can submit them
as a standalone patch series.

Note that I do not have any reproducer for the issue; the best testing
that I could offer would be some light-weight Secure Boot regression
tests.

Thanks
Laszlo


.


Re: [PATCH v4 0/2] Enable EDKII CI support for DynamicTablesPkg

Laszlo Ersek
 

On 08/17/20 08:37, Gao, Liming wrote:
Sami:
I think this change is OK. And, Shenglei and Alexei gave reviewed-by before soft feature freeze.

Mike, Leif, Andrew and Laszlo:
Have you any comments to merge this patch to edk2-stable202008 stable tag.
I'm OK with merging this series now.

Thanks
Laszlo



-----Original Message-----
From: Sami Mujawar <Sami.Mujawar@arm.com>
Sent: 2020年8月14日 21:24
To: Gao, Liming <liming.gao@intel.com>; devel@edk2.groups.io; Bret.Barkelew@microsoft.com; sean.brogan@microsoft.com; Kinney, Michael D <michael.d.kinney@intel.com>
Cc: Alexei Fedorov <Alexei.Fedorov@arm.com>; Sami Mujawar <Sami.Mujawar@arm.com>; Ard Biesheuvel <Ard.Biesheuvel@arm.com>; Matteo Carlini <Matteo.Carlini@arm.com>; Ben Adderson <Ben.Adderson@arm.com>; nd <nd@arm.com>
Subject: RE: [PATCH v4 0/2] Enable EDKII CI support for DynamicTablesPkg

Hi All,

Is there anything else needed before this patch series can be merged?
If possible, we would like this feature enabled in the edk2-stable202008.

Regards,

Sami Mujawar

-----Original Message-----
From: Sami Mujawar <sami.mujawar@arm.com>
Sent: 07 August 2020 06:30 PM
To: devel@edk2.groups.io
Cc: Sami Mujawar <Sami.Mujawar@arm.com>; Alexei Fedorov <Alexei.Fedorov@arm.com>; sean.brogan@microsoft.com; liming.gao@intel.com; michael.d.kinney@intel.com; Bret.Barkelew@microsoft.com; Ard Biesheuvel <Ard.Biesheuvel@arm.com>; Matteo Carlini <Matteo.Carlini@arm.com>; Laura Moretta <Laura.Moretta@arm.com>; nd <nd@arm.com>
Subject: [PATCH v4 0/2] Enable EDKII CI support for DynamicTablesPkg

The TianoCore EDKII project has introduced a Core CI infrastructure using TianoCore EDKII Tools PIP modules.

The v2 patch series at https://edk2.groups.io/g/devel/message/63259
adds support for building DynamicTablesPkg using the EKDII Core CI.

Splitting the v2 patch series into 2 separate series. This v4 series contains the patches for enabling Core CI for DynamicTablesPkg in .pytools and .azurepipelines i.e. the last two patches from the v2 series.

The v3 series containing the patches for DynamicTablesPkg has already been merged in edk2 master at:
- https://github.com/tianocore/edk2/commit/2d0c42fdf2cf1855b0a042ef82d848c7716adefe
- https://github.com/tianocore/edk2/commit/e3f8605a23ebe9c54ae2b17819d00e185069667d
Ref (v3 series): https://edk2.groups.io/g/devel/topic/patch_v3_0_2_add_edkii_ci/76052351

There is no code change other than splitting the v2 series.

The changes for this v4 series can be seen at:
https://github.com/samimujawar/edk2/tree/839_dynamictablespkg_ci_v4

Sami Mujawar (2):
.pytool: CI Settings to support DynamicTablesPkg
.azurepipelines: Add DynamicTablesPkg to CI matrix

.azurepipelines/templates/pr-gate-build-job.yml | 3 ++-
.pytool/CISettings.py | 2 ++
.pytool/Readme.md | 2 +-
3 files changed, 5 insertions(+), 2 deletions(-)

--
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


Re: [PATCH v5 1/1] ShellPkg/DynamicCommand: add HttpDynamicCommand

Vladimir Olovyannikov
 

Hi Gao,

Thanks for reviewing.
As you suggest, I will postpone the next patchset submission until
NetworkPkg maintainer(s) review.

-----Original Message-----
From: Gao, Zhichao <zhichao.gao@intel.com>
Sent: Sunday, August 16, 2020 6:48 PM
To: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>;
devel@edk2.groups.io
Cc: Laszlo Ersek <lersek@redhat.com>; Samer El-Haj-Mahmoud <Samer.El-
Haj-Mahmoud@arm.com>; Maciej Rabeda
<maciej.rabeda@linux.intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Fu,
Siyuan <siyuan.fu@intel.com>; Ni, Ray <ray.ni@intel.com>; Gao, Liming
<liming.gao@intel.com>; Nd <nd@arm.com>
Subject: RE: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand

Sorry for the delay reply.

See below:

-----Original Message-----
From: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
Sent: Tuesday, July 28, 2020 12:49 AM
To: devel@edk2.groups.io
Cc: Laszlo Ersek <lersek@redhat.com>; Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>; Samer El-Haj-Mahmoud
<Samer.El-
Haj-Mahmoud@arm.com>; Gao, Zhichao <zhichao.gao@intel.com>; Maciej
Rabeda <maciej.rabeda@linux.intel.com>; Wu, Jiaxin
<jiaxin.wu@intel.com>; Fu,
Siyuan <siyuan.fu@intel.com>; Ni, Ray <ray.ni@intel.com>; Gao, Liming
<liming.gao@intel.com>; Nd <nd@arm.com>
Subject: [PATCH v5 1/1] ShellPkg/DynamicCommand: add
HttpDynamicCommand

Introduce an http client utilizing EDK2 HTTP protocol, to
allow fast image downloading from http/https servers.
HTTP download speed is usually faster than tftp.
The client is based on the same approach as tftp dynamic command, and
uses the same UEFI Shell command line parameters. This makes it easy
integrating http into existing UEFI Shell scripts.
Note that to enable HTTP download, feature Pcd
gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections must
be set to TRUE.
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2860

Signed-off-by: Vladimir Olovyannikov
<vladimir.olovyannikov@broadcom.com>
CC: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
CC: Laszlo Ersek <lersek@redhat.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Nd <nd@arm.com>
---
CryptoPkg/Library/OpensslLib/openssl | 2 +-
.../DynamicCommand/HttpDynamicCommand/Http.c | 1715
+++++++++++++++++
.../DynamicCommand/HttpDynamicCommand/Http.h | 89 +
.../HttpDynamicCommand/Http.uni | 117 ++
.../HttpDynamicCommand/HttpApp.c | 53 +
.../HttpDynamicCommand/HttpApp.inf | 58 +
.../HttpDynamicCommand/HttpDynamicCommand.c | 134 ++
.../HttpDynamicCommand/HttpDynamicCommand.inf | 63 +
ShellPkg/Include/Guid/ShellLibHiiGuid.h | 5 +
ShellPkg/ShellPkg.dec | 1 +
ShellPkg/ShellPkg.dsc | 5 +
11 files changed, 2241 insertions(+), 1 deletion(-)
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.c
create mode 100644
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.inf

diff --git a/CryptoPkg/Library/OpensslLib/openssl
b/CryptoPkg/Library/OpensslLib/openssl
index e2e09d9fba11..c3656cc594da 160000
--- a/CryptoPkg/Library/OpensslLib/openssl
+++ b/CryptoPkg/Library/OpensslLib/openssl
@@ -1 +1 @@
-Subproject commit e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72
+Subproject commit c3656cc594daac8167721dde7220f0e59ae146fc
diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
new file mode 100644
index 000000000000..0565b07c3570
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
@@ -0,0 +1,1715 @@
+/** @file

+ The implementation for the 'http' Shell command.

+

+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
<BR>

+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved. <BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+**/

+

+#include "Http.h"

+

+#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32

+EFI_HII_HANDLE mHttpHiiHandle;

+

+/*

+ Constant strings and definitions related to the message

+ indicating the amount of progress in the dowloading of a HTTP
file.

+*/

+

+// Number of steps in the progression slider

+#define HTTP_PROGRESS_SLIDER_STEPS \

+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)

+

+// Size in number of characters plus one (final zero) of the message
to

+// indicate the progress of an HTTP download. The format is
"[(progress
slider:

+// 40 characters)] (nb of KBytes downloaded so far: 7 characters)
Kb".
There

+// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11
characters

+// (2 // spaces, "Kb" and seven characters for the number of KBytes).

+#define HTTP_PROGRESS_MESSAGE_SIZE \

+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)

+

+//

+// Buffer size. Note that larger buffer does not mean better speed!

+//

+#define DEFAULT_BUF_SIZE SIZE_32KB

+#define MAX_BUF_SIZE SIZE_4MB

+

+#define MIN_PARAM_COUNT 2

+#define MAX_PARAM_COUNT 4

+

+#define TIMER_MAX_TIMEOUT_S 10

+

+// File name to use when URI ends with "/"

+#define DEFAULT_HTML_FILE L"index.html"

+#define DEFAULT_HTTP_PROTO L"http"

+

+// String to delete the HTTP progress message to be able to update it
:

+// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b'

+#define HTTP_PROGRESS_DEL \

+
L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\
b\b\b\

+\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"

+

+#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b"

+// Frame for the progression slider

+#define HTTP_PROGR_FRAME L"[
]"

+

+// String descriptions for server errors

+STATIC CONST CHAR16 *ErrStatusDesc[] =

+{

+ L"400 Bad Request",

+ L"401 Unauthorized",

+ L"402 Payment required",

+ L"403 Forbidden",

+ L"404 Not Found",

+ L"405 Method not allowed",

+ L"406 Not acceptable",

+ L"407 Proxy authentication required",

+ L"408 Request time out",

+ L"409 Conflict",

+ L"410 Gone",

+ L"411 Length required",

+ L"412 Precondition failed",

+ L"413 Request entity too large",

+ L"414 Request URI to large",

+ L"415 Unsupported media type",

+ L"416 Requested range not satisfied",

+ L"417 Expectation failed",

+ L"500 Internal server error",

+ L"501 Not implemented",

+ L"502 Bad gateway",

+ L"503 Service unavailable",

+ L"504 Gateway timeout",

+ L"505 HTTP version not supported"

+};

+

+// Local File Handle

+STATIC SHELL_FILE_HANDLE mFileHandle = NULL;

+

+// Path of the local file, Unicode encoded

+STATIC CONST CHAR16 *mLocalFilePath;

+

+STATIC BOOLEAN gRequestCallbackComplete = FALSE;

+STATIC BOOLEAN gResponseCallbackComplete = FALSE;

+

+STATIC BOOLEAN gHttpError;

+

+/**

+ Cleans off leading and trailing spaces and tabs.

+

+ @param[in] String pointer to the string to trim them off.

+**/

+STATIC

+EFI_STATUS

+TrimSpaces (

+ IN CHAR16 **String

+ )

+{

+ ASSERT(String != NULL);

+ ASSERT(*String!= NULL);

+ //

+ // Remove any spaces and tabs at the beginning of the (*String).

+ //

+ while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {

+ CopyMem (

+ (*String),

+ (*String) + 1,

+ StrSize ((*String)) - sizeof((*String)[0])

+ );

+ }

+

+ //

+ // Remove any spaces and tabs at the end of the (*String).

+ //

+ while ((StrLen (*String) > 0) &&

+ (((*String)[StrLen ((*String)) - 1] == L' ') ||

+ ((*String)[StrLen ((*String)) - 1] == L'\t'))

+ ) {

+ (*String)[StrLen ((*String)) - 1] = CHAR_NULL;

+ }

+

+ return (EFI_SUCCESS);

+}

+

+

+/*

+ * Callbacks for request and response.

+ * We just acknowledge that operation has completed here.

+ */

+STATIC

+VOID

+EFIAPI

+RequestCallback (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+)

+{

+ gRequestCallbackComplete = TRUE;

+}

+

+STATIC

+VOID

+EFIAPI

+ResponseCallback (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+)

+{

+ gResponseCallbackComplete = TRUE;

+}

+

+

+/**

+ Check and convert the UINT16 option values of the 'http' command

+

+ @param[in] ValueStr Value as an Unicode encoded string

+ @param[out] Value UINT16 value

+

+ @return TRUE The value was returned.

+ @return FALSE A parsing error occured.

+**/

+STATIC

+BOOLEAN

+StringToUint16 (

+ IN CONST CHAR16 *ValueStr,

+ OUT UINT16 *Value

+ );

+

+/**

+ Get the name of the NIC.

+

+ @param[in] ControllerHandle The network physical device handle.

+ @param[in] NicNumber The network physical device number.

+ @param[out] NicName Address where to store the NIC name.

+ The memory area has to be at least

+
IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH

+ double byte wide.

+

+ @return EFI_SUCCESS The name of the NIC was returned.

+ @return Others The creation of the child for the Managed

+ Network Service failed or the opening of

+ the Managed Network Protocol failed or

+ the operational parameters for the

+ Managed Network Protocol could not be

+ read.

+**/

+STATIC

+EFI_STATUS

+GetNicName (

+ IN EFI_HANDLE ControllerHandle,

+ IN UINTN NicNumber,

+ OUT CHAR16 *NicName

+ );

+

+/**

+ Create a child for the service identified by its service binding
protocol
GUID

+ and get from the child the interface of the protocol identified by
its
GUID.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the

+ service to be created.

+ @param[in] ProtocolGuid GUID of the protocol to be
open.

+ @param[out] ChildHandle Address where the handler
of the

+ created child is returned.
NULL is

+ returned in case of error.

+ @param[out] Interface Address where a pointer to
the

+ protocol interface is
returned in

+ case of success.

+

+ @return EFI_SUCCESS The child was created and the protocol
opened.

+ @return Others Either the creation of the child or the
opening

+ of the protocol failed.

+**/

+STATIC

+EFI_STATUS

+CreateServiceChildAndOpenProtocol (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ OUT EFI_HANDLE *ChildHandle,

+ OUT VOID **Interface

+ );

+

+/**

+ Close the protocol identified by its GUID on the child handle of
the
service

+ identified by its service binding protocol GUID, then destroy the
child

+ handle.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the

+ service to be destroyed.

+ @param[in] ProtocolGuid GUID of the protocol to be
closed.

+ @param[in] ChildHandle Handle of the child to be
destroyed.

+

+**/

+STATIC

+VOID

+CloseProtocolAndDestroyServiceChild (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ IN EFI_HANDLE ChildHandle

+ );

+

+

+/**

+ Worker function that download the data of a file from an HTTP
server
given

+ the path of the file and its size.

+

+ @param[in] Context A pointer to the download context.

+

+ @retval EFI_SUCCESS The file was downloaded.

+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.

+ @retval Others The downloading of the file

+ from the server failed.

+

+**/

+STATIC

+EFI_STATUS

+DownloadFile (

+ IN DOWNLOAD_CONTEXT *Context

+ );

+

+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {

+ {L"-i", TypeValue},

+ {L"-k", TypeFlag},

+ {L"-l", TypeValue},

+ {L"-s", TypeValue},

+ {L"-t", TypeValue},

+ {NULL , TypeMax}

+ };

+

+/**

+ Function for 'http' command.

+

+ @param[in] ImageHandle Handle to the Image (NULL if Internal).

+ @param[in] SystemTable Pointer to the System Table (NULL if
Internal).

+

+ @return SHELL_SUCCESS The 'http' command completed
successfully.

+ @return SHELL_ABORTED The Shell Library initialization
failed.

+ @return SHELL_INVALID_PARAMETER At least one of the command's
arguments is

+ not valid.

+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.

+ @return SHELL_NOT_FOUND Network Interface Card not found.

+ @return SHELL_UNSUPPORTED Command was valid, but the server
returned

+ a status code indicating some
error.

+ Examine the file requested for
error body.

+

+**/

+SHELL_STATUS

+RunHttp (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ LIST_ENTRY *CheckPackage;

+ UINTN ParamCount;

+ UINTN HandleCount;

+ UINTN NicNumber;

+ UINTN InitialSize;

+ UINTN ParamOffset;

+ UINTN StartSize;

+ CHAR16 *ProblemParam;

+ CHAR16
NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];

+ CHAR16 *Walker1;

+ CHAR16 *VStr;

+ CONST CHAR16 *UserNicName;

+ CONST CHAR16 *ValueStr;

+ CONST CHAR16 *RemoteFilePath;

+ CONST CHAR16 *Walker;

+ EFI_HTTP_CONFIG_DATA HttpConfigData;

+ EFI_HTTPv4_ACCESS_POINT IPv4Node;

+ EFI_HANDLE *Handles;

+ EFI_HANDLE ControllerHandle;

+ EFI_HANDLE HttpChildHandle;

+ DOWNLOAD_CONTEXT Context;

+ BOOLEAN NicFound;

+

+ ProblemParam = NULL;

+ RemoteFilePath = NULL;

+ NicFound = FALSE;

+ Handles = NULL;

+

+ //

+ // Initialize the Shell library (we must be in non-auto-init...)

+ //

+ ParamOffset = 0;

+ gHttpError = FALSE;

+

+ Status = ShellInitialize ();

+ if (EFI_ERROR (Status)) {

+ ASSERT_EFI_ERROR (Status);

+ return SHELL_ABORTED;

+ }

+

+ ZeroMem (&Context, sizeof (Context));

+

+ //

+ // Parse the command line.

+ //

+ Status = ShellCommandLineParse (

+ ParamList,

+ &CheckPackage,

+ &ProblemParam,

+ TRUE);
I prefer to put ');' in next line like other functions.


+ if (EFI_ERROR (Status)) {

+ if ((Status == EFI_VOLUME_CORRUPTED) &&

+ (ProblemParam != NULL) ) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mHttpHiiHandle,

+ HTTP_APP_NAME, ProblemParam

+ );

+ SHELL_FREE_NON_NULL (ProblemParam);

+ } else {

+ ASSERT (FALSE);

+ }

+

+ goto Error;

+ }

+

+ //

+ // Check the number of parameters

+ //

+ Status = EFI_INVALID_PARAMETER;

+

+ ParamCount = ShellCommandLineGetCount (CheckPackage);

+ if (ParamCount > MAX_PARAM_COUNT) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),

+ mHttpHiiHandle, HTTP_APP_NAME

+ );

+ goto Error;

+ }

+

+ if (ParamCount < MIN_PARAM_COUNT) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),

+ mHttpHiiHandle, HTTP_APP_NAME

+ );

+ goto Error;

+ }

+

+ ZeroMem (&HttpConfigData, sizeof (HttpConfigData));

+ ZeroMem (&IPv4Node, sizeof (IPv4Node));

+ IPv4Node.UseDefaultAddress = TRUE;

+

+ HttpConfigData.HttpVersion = HttpVersion11;

+ HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;

+

+ //

+ // Get the host address (not necessarily IPv4 format)

+ //

+ ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);

+ if (!ValueStr) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
mHttpHiiHandle,

+ HTTP_APP_NAME, ValueStr

+ );

+ goto Error;

+ } else {

+ StartSize = 0;

+ if (!StrStr (ValueStr, L"://")) {

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ DEFAULT_HTTP_PROTO,

+ StrLen (DEFAULT_HTTP_PROTO)

+ );

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ L"://",

+ StrLen (L"://")

+ );

+ VStr = (CHAR16 *)ValueStr;

+ } else {

+ VStr = StrStr (ValueStr, L"://") + StrLen (L"://");

+ }

+

+ for (Walker1 = VStr; *Walker1; Walker1++) {

+ if (*Walker1 == L'/') {

+ break;

+ }

+ }

+

+ if (*Walker1 == L'/') {

+ ParamOffset = 1;

+ RemoteFilePath = Walker1;

+ }

+

+ Context.ServerAddrAndProto = StrnCatGrow (

+ &Context.ServerAddrAndProto,

+ &StartSize,

+ ValueStr,

+ StrLen (ValueStr) - StrLen
(Walker1)

+ );

+ if (!Context.ServerAddrAndProto) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+ }

+

+ if (!RemoteFilePath) {

+ RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);

+ if (!RemoteFilePath) {

+ // If no path given, assume just "/"

+ RemoteFilePath = L"/";

+ }

+ }

+

+ TrimSpaces ((CHAR16 **)&RemoteFilePath);

+

+ if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {

+ mLocalFilePath = ShellCommandLineGetRawValue (

+ CheckPackage,

+ MAX_PARAM_COUNT - 1 - ParamOffset);

+ } else {

+ Walker = RemoteFilePath + StrLen (RemoteFilePath);

+ while ((--Walker) >= RemoteFilePath) {

+ if ((*Walker == L'\\') ||

+ (*Walker == L'/' ) ) {
It is better to remove the useless space in the above line at the end of
'if'
condition.


+ break;

+ }

+ }

+

+ mLocalFilePath = Walker + 1;

+ }

+

+ if (!StrLen (mLocalFilePath)) {

+ mLocalFilePath = DEFAULT_HTML_FILE;

+ }

+

+ InitialSize = 0;

+ Context.URI = StrnCatGrow (

+ &Context.URI,

+ &InitialSize,

+ RemoteFilePath,

+ StrLen (RemoteFilePath)

+ );

+ if (!Context.URI) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ //

+ // Get the name of the Network Interface Card to be used if any.

+ //

+ UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");

+ if (ValueStr != NULL) {

+ if (!StringToUint16 (

+ ValueStr,

+ &HttpConfigData.AccessPoint.IPv4Node->LocalPort

+ )

+ ) {
I suggest to align the end ')' of StringToUint16 to align with the
parameters.
And the end ')' of 'if' to go right next to the end ')' of
StringToUint16.
OK, will do.


+ goto Error;

+ }

+ }

+

+ Context.BufferSize = DEFAULT_BUF_SIZE;

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");

+ if (ValueStr != NULL) {

+ Context.BufferSize = ShellStrToUintn (ValueStr);

+ if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),

+ mHttpHiiHandle, HTTP_APP_NAME, ValueStr

+ );

+ goto Error;

+ }

+ }

+

+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");

+ if (ValueStr != NULL) {

+ HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn
(ValueStr);

I am not sure if it is fine to transfer '-1' as time out value when the
-t with
invalid number string. It depends on the NetworkPkg maintainers' review.

I am OK with other part of the patch. But I still need NetworkPkg
maintainers'
help to review above issue and the implementation.
There is no need to resend another patch if NetworkPkg maintainers are
OK
with above issue and the implementation.
OK, I will postpone submission of the patch until NetworkPkg
maintainter(s) review.

Thanks,
Zhichao
Thank you,
Vladimir

+ }

+

+ //

+ // Locate all HTTP Service Binding protocols

+ //

+ Status = gBS->LocateHandleBuffer (

+ ByProtocol,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ NULL,

+ &HandleCount,

+ &Handles

+ );

+ if (EFI_ERROR (Status) || (HandleCount == 0)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NO_NIC),
mHttpHiiHandle

+ );

+ if (!EFI_ERROR (Status)) {

+ Status = EFI_NOT_FOUND;

+ }

+

+ goto Error;

+ }

+

+ Status = EFI_NOT_FOUND;

+

+ for (NicNumber = 0;

+ (NicNumber < HandleCount) && (Status != EFI_SUCCESS);

+ NicNumber++) {

+ ControllerHandle = Handles[NicNumber];

+

+ Status = GetNicName (ControllerHandle, NicNumber, NicName);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NAME),

+ mHttpHiiHandle, NicNumber, Status

+ );

+ continue;

+ }

+

+ if (UserNicName != NULL) {

+ if (StrCmp (NicName, UserNicName) != 0) {

+ Status = EFI_NOT_FOUND;

+ continue;

+ }

+ NicFound = TRUE;

+ }

+

+ Status = CreateServiceChildAndOpenProtocol (

+ ControllerHandle,

+ &gEfiHttpServiceBindingProtocolGuid,

+ &gEfiHttpProtocolGuid,

+ &HttpChildHandle,

+ (VOID**)&Context.Http

+ );

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL),

+ mHttpHiiHandle, NicName, Status

+ );

+ continue;

+ }

+

+ Status = Context.Http->Configure (Context.Http, &HttpConfigData);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_CONFIGURE),

+ mHttpHiiHandle, NicName, Status

+ );

+ continue;

+ }

+

+ Context.Flags = 0;

+ if (ShellCommandLineGetFlag (CheckPackage, L"-m")) {

+ Context.Flags |= DL_FLAG_TIME;

+ }

+

+ if (ShellCommandLineGetFlag (CheckPackage, L"-k")) {

+ Context.Flags |= DL_FLAG_KEEP_BAD;

+ }

+

+ Status = DownloadFile (&Context);

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle

+ );

+

+ CloseProtocolAndDestroyServiceChild (

+ ControllerHandle,

+ &gEfiHttpServiceBindingProtocolGuid,

+ &gEfiHttpProtocolGuid,

+ HttpChildHandle

+ );

+

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),

+ mHttpHiiHandle, RemoteFilePath, NicName, Status

+ );

+ // If a user aborted the operation, do not try another
controller.

+ if (Status == EFI_ABORTED) {

+ goto Error;

+ }

+ }

+

+ if (gHttpError) {

+ //

+ // This is not related to connection, so no need to repeat with

+ // another interface.

+ //

+ break;

+ }

+ }

+

+ if ((UserNicName != NULL) && (!NicFound)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND),

+ mHttpHiiHandle, UserNicName

+ );

+ }

+

+Error:

+ ShellCommandLineFreeVarList (CheckPackage);

+ SHELL_FREE_NON_NULL (Handles);

+ SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);

+ SHELL_FREE_NON_NULL (Context.URI);

+

+ return Status & ~MAX_BIT;

+}

+

+/**

+ Check and convert the UINT16 option values of the 'http' command

+

+ @param[in] ValueStr Value as an Unicode encoded string

+ @param[out] Value UINT16 value

+

+ @return TRUE The value was returned.

+ @return FALSE A parsing error occured.

+**/

+STATIC

+BOOLEAN

+StringToUint16 (

+ IN CONST CHAR16 *ValueStr,

+ OUT UINT16 *Value

+ )

+{

+ UINTN Val;

+

+ Val = ShellStrToUintn (ValueStr);

+ if (Val > MAX_UINT16) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),

+ mHttpHiiHandle, HTTP_APP_NAME, ValueStr

+ );

+ return FALSE;

+ }

+

+ *Value = (UINT16)Val;

+ return TRUE;

+}

+

+/**

+ Get the name of the NIC.

+

+ @param[in] ControllerHandle The network physical device handle.

+ @param[in] NicNumber The network physical device number.

+ @param[out] NicName Address where to store the NIC name.

+ The memory area has to be at least

+
IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH

+ double byte wide.

+

+ @return EFI_SUCCESS The name of the NIC was returned.

+ @return Others The creation of the child for the Managed

+ Network Service failed or the opening of

+ the Managed Network Protocol failed or

+ the operational parameters for the

+ Managed Network Protocol could not be

+ read.

+**/

+STATIC

+EFI_STATUS

+GetNicName (

+ IN EFI_HANDLE ControllerHandle,

+ IN UINTN NicNumber,

+ OUT CHAR16 *NicName

+ )

+{

+ EFI_STATUS Status;

+ EFI_HANDLE MnpHandle;

+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;

+ EFI_SIMPLE_NETWORK_MODE SnpMode;

+

+ Status = CreateServiceChildAndOpenProtocol (

+ ControllerHandle,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ &gEfiManagedNetworkProtocolGuid,

+ &MnpHandle,

+ (VOID**)&Mnp

+ );

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);

+ if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {

+ goto Error;

+ }

+

+ UnicodeSPrint (

+ NicName,

+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,

+ SnpMode.IfType == NET_IFTYPE_ETHERNET ?

+ L"eth%d" :

+ L"unk%d",

+ NicNumber

+ );

+

+ Status = EFI_SUCCESS;

+

+Error:

+

+ if (MnpHandle != NULL) {

+ CloseProtocolAndDestroyServiceChild (

+ ControllerHandle,

+ &gEfiManagedNetworkServiceBindingProtocolGuid,

+ &gEfiManagedNetworkProtocolGuid,

+ MnpHandle

+ );

+ }

+

+ return Status;

+}

+

+/**

+ Create a child for the service identified by its service binding
protocol
GUID

+ and get from the child the interface of the protocol identified by
its
GUID.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the

+ service to be created.

+ @param[in] ProtocolGuid GUID of the protocol to be
open.

+ @param[out] ChildHandle Address where the handler
of the

+ created child is returned.
NULL is

+ returned in case of error.

+ @param[out] Interface Address where a pointer to
the

+ protocol interface is
returned in

+ case of success.

+

+ @return EFI_SUCCESS The child was created and the protocol
opened.

+ @return Others Either the creation of the child or the
opening

+ of the protocol failed.

+**/

+STATIC

+EFI_STATUS

+CreateServiceChildAndOpenProtocol (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ OUT EFI_HANDLE *ChildHandle,

+ OUT VOID **Interface

+ )

+{

+ EFI_STATUS Status;

+

+ *ChildHandle = NULL;

+ Status = NetLibCreateServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ ChildHandle

+ );

+ if (!EFI_ERROR (Status)) {

+ Status = gBS->OpenProtocol (

+ *ChildHandle,

+ ProtocolGuid,

+ Interface,

+ gImageHandle,

+ ControllerHandle,

+ EFI_OPEN_PROTOCOL_GET_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ NetLibDestroyServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ *ChildHandle

+ );

+ *ChildHandle = NULL;

+ }

+ }

+

+ return Status;

+}

+

+/**

+ Close the protocol identified by its GUID on the child handle of
the
service

+ identified by its service binding protocol GUID, then destroy the
child

+ handle.

+

+ @param[in] ControllerHandle Controller handle.

+ @param[in] ServiceBindingProtocolGuid Service binding protocol
GUID
of the

+ service to be destroyed.

+ @param[in] ProtocolGuid GUID of the protocol to be
closed.

+ @param[in] ChildHandle Handle of the child to be
destroyed.

+

+**/

+STATIC

+VOID

+CloseProtocolAndDestroyServiceChild (

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_GUID *ServiceBindingProtocolGuid,

+ IN EFI_GUID *ProtocolGuid,

+ IN EFI_HANDLE ChildHandle

+ )

+{

+ gBS->CloseProtocol (

+ ChildHandle,

+ ProtocolGuid,

+ gImageHandle,

+ ControllerHandle

+ );

+

+ NetLibDestroyServiceChild (

+ ControllerHandle,

+ gImageHandle,

+ ServiceBindingProtocolGuid,

+ ChildHandle

+ );

+}

+

+/**

+ Wait until operation completes. Completion is indicated by

+ setting of an appropriate variable.

+

+ @param[in] Context A pointer to the HTTP download
context.

+ @param[in] CallBackComplete A pointer to the callback
completion

+ variable set by the callback.

+

+ @return EFI_SUCCESS Callback signalled completion.

+ @return EFI_TIMEOUT Timed out waiting for completion.

+ @return Others Error waiting for completion.

+**/

+STATIC

+EFI_STATUS

+WaitForCompletion (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN OUT BOOLEAN *CallBackComplete

+ )

+{

+ EFI_STATUS Status;

+ EFI_EVENT WaitEvt;

+

+ Status = EFI_SUCCESS;

+

+ // Use a timer to measure timeout. Cannot use Stall here!

+ Status = gBS->CreateEvent (

+ EVT_TIMER,

+ TPL_CALLBACK,

+ NULL,

+ NULL,

+ &WaitEvt

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ if (!EFI_ERROR (Status)) {

+ Status = gBS->SetTimer(

+ WaitEvt,

+ TimerRelative,

+ EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S)

+ );

+

+ ASSERT_EFI_ERROR (Status);

+ }

+

+ while (! *CallBackComplete &&

+ (!EFI_ERROR (Status)) &&

+ EFI_ERROR (gBS->CheckEvent (WaitEvt))

+ ) {

+ Status = Context->Http->Poll (Context->Http);

+ }

+

+ gBS->SetTimer (WaitEvt, TimerCancel, 0);

+ gBS->CloseEvent (WaitEvt);

+

+ if (*CallBackComplete) {

+ return EFI_SUCCESS;

+ }

+

+ if (!EFI_ERROR (Status)) {

+ Status = EFI_TIMEOUT;

+ }

+

+ return Status;

+}

+

+/**

+ Generate and send a request to the http server.

+

+ @param[in] Context HTTP download context.

+ @param[in] DownloadUrl Fully qualified URL to be
downloaded.

+

+ @return EFI_SUCCESS Request has been sent successfully.

+ @return EFI_INVALID_PARAMETER Invalid URL.

+ @return EFI_OUT_OF_RESOURCES Out of memory.

+ @return EFI_DEVICE_ERROR If HTTPS is used, this probably

+ means that TLS support either was
not

+ installed or not configured.

+ @return Others Error sending the request.

+**/

+

+STATIC

+EFI_STATUS

+SendRequest (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_HTTP_REQUEST_DATA RequestData;

+ EFI_HTTP_HEADER RequestHeader;

+ EFI_HTTP_MESSAGE RequestMessage;

+ EFI_STATUS Status;

+ CHAR16 *Host;

+ UINTN StringSize;

+

+ ZeroMem (&RequestData, sizeof (RequestData));

+ ZeroMem (&RequestHeader, sizeof (RequestHeader));

+ ZeroMem (&RequestMessage, sizeof (RequestMessage));

+ ZeroMem (&Context->RequestToken, sizeof (Context-
RequestToken));

+

+ RequestHeader.FieldName = "Host";

+

+ Host = (CHAR16 *)Context->ServerAddrAndProto;

+ while (*Host != CHAR_NULL && *Host != L'/') {

+ Host++;

+ }

+

+ if (*Host == CHAR_NULL) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ //

+ // Get the next slash

+ //

+ Host++;

+ //

+ // And now the host name

+ //

+ Host++;

+

+ StringSize = StrLen (Host) + 1;

+ RequestHeader.FieldValue = AllocatePool (StringSize);

+ if (!RequestHeader.FieldValue) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ UnicodeStrToAsciiStrS (Host, RequestHeader.FieldValue,
StringSize);

+

+ RequestMessage.HeaderCount++;

+

+ RequestData.Method = HttpMethodGet;

+ RequestData.Url = DownloadUrl;

+

+ RequestMessage.Data.Request = &RequestData;

+ RequestMessage.Headers = &RequestHeader;

+ RequestMessage.BodyLength = 0;

+ RequestMessage.Body = NULL;

+ Context->RequestToken.Event = NULL;

+

+ //

+ // Completion callback event to be set when Request completes.

+ //

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ RequestCallback,

+ Context,

+ &Context->RequestToken.Event

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ Context->RequestToken.Status = EFI_SUCCESS;

+ Context->RequestToken.Message = &RequestMessage;

+ gRequestCallbackComplete = FALSE;

+ Status = Context->Http->Request (Context->Http, &Context-
RequestToken);

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ Status = WaitForCompletion (Context, &gRequestCallbackComplete);

+ if (EFI_ERROR (Status)) {

+ Context->Http->Cancel (Context->Http, &Context->RequestToken);

+ }

+Error:

+ SHELL_FREE_NON_NULL (RequestHeader.FieldValue);

+ if (Context->RequestToken.Event) {

+ gBS->CloseEvent (Context->RequestToken.Event);

+ ZeroMem (&Context->RequestToken, sizeof (Context-
RequestToken));

+ }

+

+ return Status;

+}

+

+/**

+ Update the progress of a file download

+ This procedure is called each time a new HTTP body portion is
received.

+

+ @param[in] Context HTTP download context.

+ @param[in] DownloadLen Portion size, in bytes.

+ @param[in] Buffer The pointer to the parsed buffer.

+

+ @retval EFI_SUCCESS Portion saved.

+ @retval Other Error saving the portion.

+

+**/

+STATIC

+EFI_STATUS

+EFIAPI

+SavePortion (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN UINTN DownloadLen,

+ IN CHAR8 *Buffer

+ )

+{

+ CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE];

+ UINTN NbOfKb;

+ UINTN Index;

+ UINTN LastStep;

+ UINTN Step;

+ EFI_STATUS Status;

+

+ LastStep = 0;

+ Step = 0;

+ ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes);

+ Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer);

+ if (EFI_ERROR (Status)) {

+ if (Context->ContentDownloaded > 0) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), mHttpHiiHandle

+ );

+ }

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_WRITE),

+ mHttpHiiHandle, mLocalFilePath, Status

+ );

+

+ return Status;

+ }

+

+ if (Context->ContentDownloaded == 0) {

+ ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME);

+ }

+

+ Context->ContentDownloaded += DownloadLen;

+ NbOfKb = Context->ContentDownloaded >> 10;

+

+ Progress[0] = L'\0';

+ if (Context->ContentLength) {

+ LastStep = (Context->LastReportedNbOfBytes *
HTTP_PROGRESS_SLIDER_STEPS) /

+ Context->ContentLength;

+ Step = (Context->ContentDownloaded *
HTTP_PROGRESS_SLIDER_STEPS) /

+ Context->ContentLength;

+ }

+

+ Context->LastReportedNbOfBytes = Context->ContentDownloaded;

+

+ if (Step <= LastStep) {

+ if (!Context->ContentLength) {

+ //

+ // Update downloaded size, there is no length info available.

+ //

+ ShellPrintEx (-1, -1, L"%s", HTTP_KB);

+ ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb);

+ }

+

+ return EFI_SUCCESS;

+ }

+

+ ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL);

+

+ Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE,
HTTP_PROGR_FRAME);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ for (Index = 1; Index < Step; Index++) {

+ Progress[Index] = L'=';

+ }

+

+ if (Step) {

+ Progress[Step] = L'>';

+ }

+

+ UnicodeSPrint (

+ Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1,

+ sizeof (Progress) - sizeof (HTTP_PROGR_FRAME),

+ L" %7d Kb",

+ NbOfKb

+ );

+

+

+ ShellPrintEx (-1, -1, L"%s", Progress);

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Replace the original Host and URI with Host and URI returned by the

+ HTTP server in 'Location' header (redirection).

+

+ @param[in] Location A pointer to the 'Location' string

+ provided by HTTP server.

+ @param[in] Context A pointer to HTTP download context.

+ @param[in] DownloadUrl Fully qualified HTTP URL.

+

+ @return EFI_SUCCESS Host and URI were successfully set.

+ @return EFI_OUT_OF_RESOURCES Error setting Host or URI.

+**/

+

+STATIC

+EFI_STATUS

+SetHostURI (

+ IN CHAR8 *Location,

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_STATUS Status;

+ UINTN StringSize;

+ UINTN FirstStep;

+ UINTN Idx;

+ UINTN Step;

+ CHAR8 *Walker;

+ CHAR16 *Temp;

+ CHAR8 *Tmp;

+ CHAR16 *Url;

+ BOOLEAN IsAbEmptyUrl;

+

+ Tmp = NULL;

+ Url = NULL;

+ IsAbEmptyUrl = FALSE;

+ FirstStep = 0;

+

+ StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));

+ Url = AllocateZeroPool (StringSize);

+ if (!Url) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Location,

+ Url,

+ StringSize

+ );

+

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ //

+ // If an HTTP server redirects to the same location more than once,

+ // then stop attempts and tell it is not reachable.

+ //

+ if (!StrCmp (Url, DownloadUrl)) {

+ Status = EFI_NO_MAPPING;

+ goto Error;

+ }

+

+ if (AsciiStrLen (Location) > 2) {

+ // Some servers return 'Location: //server/resource'

+ IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');

+ if (IsAbEmptyUrl) {

+ // Skip first "//"

+ Location += 2;

+ FirstStep = 1;

+ }

+ }

+

+ if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {

+ Idx = 0;

+ Walker = Location;

+

+ for (Step = FirstStep; Step < 2; Step++) {

+ for (; *Walker != '/' && *Walker != '\0'; Walker++) {

+ Idx++;

+ }

+ if (!Step) {

+ //

+ // Skip "//"

+ //

+ Idx += 2;

+ Walker += 2;

+ }

+ }

+

+ Tmp = AllocateZeroPool (Idx + 1);

+ if (!Tmp) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ CopyMem (Tmp, Location, Idx);

+

+ //

+ // Location now points to URI

+ //

+ Location += Idx;

+ StringSize = (Idx + 1) * sizeof (CHAR16);

+

+ SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);

+

+ Temp = AllocateZeroPool (StringSize);

+ if (!Temp) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Tmp,

+ Temp,

+ StringSize

+ );

+ if (EFI_ERROR (Status)) {

+ SHELL_FREE_NON_NULL (Temp);

+ goto Error;

+ }

+

+ Idx = 0;

+ if (IsAbEmptyUrl) {

+ Context->ServerAddrAndProto = StrnCatGrow (

+ &Context->ServerAddrAndProto,

+ &Idx,

+ L"http://",

+ StrLen (L"http://")

+ );

+ }

+

+ Context->ServerAddrAndProto = StrnCatGrow (

+ &Context->ServerAddrAndProto,

+ &Idx,

+ Temp,

+ StrLen (Temp)

+ );

+ SHELL_FREE_NON_NULL (Temp);

+ if (!Context->ServerAddrAndProto) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+ }

+

+ SHELL_FREE_NON_NULL (Context->URI);

+

+ StringSize = AsciiStrSize (Location) * sizeof (CHAR16);

+ Context->URI = AllocateZeroPool (StringSize);

+ if (!Context->URI) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ //

+ // Now make changes to the URI part.

+ //

+ Status = AsciiStrToUnicodeStrS (

+ (CONST CHAR8 *)Location,

+ Context->URI,

+ StringSize

+ );

+Error:

+ SHELL_FREE_NON_NULL (Tmp);

+ SHELL_FREE_NON_NULL (Url);

+ return Status;

+}

+

+/**

+ Message parser callback.

+ Save a portion of HTTP body.

+

+ @param[in] EventType Type of event. Can be either

+ OnComplete or OnData.

+ @param[in] Data A pointer to the buffer with data.

+ @param[in] Length Data length of this portion.

+ @param[in] Context A pointer to the HTTP download
context.

+

+ @return EFI_SUCCESS The portion was processed successfully.

+ @return Other Error returned by SavePortion.

+**/

+

+STATIC

+EFI_STATUS

+EFIAPI

+ParseMsg (

+ IN HTTP_BODY_PARSE_EVENT EventType,

+ IN CHAR8 *Data,

+ IN UINTN Length,

+ IN VOID *Context

+ )

+{

+ if (!Data || (EventType == BodyParseEventOnComplete) || !Context) {

+ return EFI_SUCCESS;

+ }

+

+ return SavePortion (Context, Length, Data);

+}

+

+

+/**

+ Get HTTP server response and collect the whole body as a file.

+ Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR).

+ Note that even if HTTP server returns an error code, it might send

+ the body as well. This body will be collected in the resultant
file.

+

+ @param[in] Context A pointer to the HTTP download
context.

+ @param[in] DownloadedUrl A pointer to the fully qualified URL
to
download.

+

+ @return EFI_SUCCESS Valid file. Body successfully
collected.

+ @return EFI_HTTP_ERROR Response is a valid HTTP response, but
the

+ HTTP server

+ indicated an error (HTTP code >= 400).

+ Response body MAY contain full

+ HTTP server response.

+ @return Others Error getting the reponse from the
HTTP server.

+ Response body is not collected.

+**/

+STATIC

+EFI_STATUS

+GetResponse (

+ IN DOWNLOAD_CONTEXT *Context,

+ IN CHAR16 *DownloadUrl

+ )

+{

+ EFI_HTTP_RESPONSE_DATA ResponseData;

+ EFI_HTTP_MESSAGE ResponseMessage;

+ EFI_HTTP_HEADER *Header;

+ EFI_STATUS Status;

+ VOID *MsgParser;

+ CONST CHAR16 *Desc;

+ BOOLEAN IsTrunked;

+ BOOLEAN Redirection;

+

+ ZeroMem (&ResponseData, sizeof (ResponseData));

+ ZeroMem (&ResponseMessage, sizeof (ResponseMessage));

+ ZeroMem (&Context->ResponseToken, sizeof (Context-
ResponseToken));

+ IsTrunked = FALSE;

+

+ ResponseMessage.Body = Context->Buffer;

+ Context->ResponseToken.Status = EFI_SUCCESS;

+ Context->ResponseToken.Message = &ResponseMessage;

+ Context->ContentLength = 0;

+ Context->Status = REQ_OK;

+ MsgParser = NULL;

+ ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;

+ ResponseMessage.Data.Response = &ResponseData;

+ Context->ResponseToken.Event = NULL;

+

+ do {

+ SHELL_FREE_NON_NULL (ResponseMessage.Headers);

+ ResponseMessage.HeaderCount = 0;

+ gResponseCallbackComplete = FALSE;

+ ResponseMessage.BodyLength = Context->BufferSize;

+

+ if (ShellGetExecutionBreakFlag ()) {

+ Status = EFI_ABORTED;

+ break;

+ }

+

+ if (!Context->ContentDownloaded && !Context-
ResponseToken.Event) {

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ ResponseCallback,

+ Context,

+ &Context->ResponseToken.Event

+ );

+ ASSERT_EFI_ERROR (Status);

+ } else {

+ ResponseMessage.Data.Response = NULL;

+ }

+

+ if (EFI_ERROR (Status)) {

+ break;

+ }

+

+ Status = Context->Http->Response (Context->Http, &Context-
ResponseToken);
+ if (EFI_ERROR (Status)) {

+ break;

+ }

+

+ Status = WaitForCompletion (Context, &gResponseCallbackComplete);

+ if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {

+ Status = EFI_SUCCESS;

+ }

+

+ if (EFI_ERROR (Status)) {

+ Context->Http->Cancel (Context->Http, &Context->ResponseToken);

+ break;

+ }

+

+ if (!Context->ContentDownloaded) {

+ Redirection =

+ ((ResponseData.StatusCode >=
HTTP_STATUS_300_MULTIPLE_CHOICES)
&&

+ (ResponseData.StatusCode <=
HTTP_STATUS_307_TEMPORARY_REDIRECT)

+ ) ||

+ (ResponseData.StatusCode ==
HTTP_STATUS_308_PERMANENT_REDIRECT);

+

+ if (Redirection) {

+ //

+ // Need to repeat the request with new Location (server
redirected).

+ //

+ Context->Status = REQ_NEED_REPEAT;

+

+ Header = HttpFindHeader (

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ "Location"

+ );

+ if (Header) {

+ Status = SetHostURI (Header->FieldValue, Context,
DownloadUrl);

+ if (Status == EFI_NO_MAPPING) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),

+ mHttpHiiHandle, Context->ServerAddrAndProto,

+ L"Recursive HTTP server relocation",

+ Context->URI

+ );

+ }

+ } else {

+ //

+ // Bad reply from the server. Server must specify the
location.

+ // Indicate that resource was not found, and no body
collected.

+ //

+ Status = EFI_NOT_FOUND;

+ }

+

+ Context->Http->Cancel (Context->Http,
&Context->ResponseToken);

+ break;

+ }

+

+ //

+ // Init message-body parser by header information.

+ //

+ if (!MsgParser) {

+ Status = HttpInitMsgParser (

+ ResponseMessage.Data.Request->Method,

+ ResponseData.StatusCode,

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ ParseMsg,

+ Context,

+ &MsgParser

+ );

+ if (EFI_ERROR (Status)) {

+ break;

+ }

+ }

+

+ //

+ // If it is a trunked message, rely on the parser.

+ //

+ Header = HttpFindHeader (

+ ResponseMessage.HeaderCount,

+ ResponseMessage.Headers,

+ "Transfer-Encoding"

+ );

+ IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue,
"chunked"));

+

+ HttpGetEntityLength (MsgParser, &Context->ContentLength);

+

+ if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST
&&

+ (ResponseData.StatusCode !=
HTTP_STATUS_308_PERMANENT_REDIRECT)

+ ) {

+ //

+ // Server reported an error via Response code.

+ // Collect the body if any.

+ //

+ if (!gHttpError) {

+ gHttpError = TRUE;

+

+ Desc = ErrStatusDesc[ResponseData.StatusCode -

+ HTTP_STATUS_400_BAD_REQUEST];

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),

+ mHttpHiiHandle, Context->ServerAddrAndProto,

+ Desc,

+ Context->URI

+ );

+

+ //

+ // This gives an RFC HTTP error.

+ //

+ Context->Status = ShellStrToUintn (Desc);

+ }

+ }

+ }

+

+ // Do NOT try to parse an empty body.

+ if (ResponseMessage.BodyLength || IsTrunked) {

+ Status = HttpParseMessageBody (

+ MsgParser,

+ ResponseMessage.BodyLength,

+ ResponseMessage.Body

+ );

+ }

+ } while (!HttpIsMessageComplete (MsgParser) &&

+ !EFI_ERROR (Status) &&

+ ResponseMessage.BodyLength

+ );

+

+ SHELL_FREE_NON_NULL (MsgParser);

+ if (Context->ResponseToken.Event) {

+ gBS->CloseEvent (Context->ResponseToken.Event);

+ ZeroMem (&Context->ResponseToken, sizeof (Context-
ResponseToken));

+ }

+

+ return Status;

+}

+

+/**

+ Worker function that downloads the data of a file from an HTTP
server
given

+ the path of the file and its size.

+

+ @param[in] Context A pointer to the HTTP download
context.

+

+ @retval EFI_SUCCESS The file was downloaded.

+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.

+ #retval EFI_HTTP_ERROR The server returned a valid HTTP
error.

+ Examine the mLocalFilePath file

+ to get error body.

+ @retval Others The downloading of the file from the
server

+ failed.

+

+**/

+STATIC

+EFI_STATUS

+DownloadFile (

+ IN DOWNLOAD_CONTEXT *Context

+ )

+{

+ EFI_STATUS Status;

+ CHAR16 *DownloadUrl;

+ UINTN UrlSize;

+

+ ASSERT (Context);

+ if (!Context) {

+ return EFI_INVALID_PARAMETER;

+ }

+

+ DownloadUrl = NULL;

+

+ Context->Buffer = AllocatePool (Context->BufferSize);

+ if (!Context->Buffer) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto ON_EXIT;

+ }

+

+ //

+ // OPEN FILE

+ //

+ if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {

+ ShellDeleteFileByName (mLocalFilePath);

+ }

+

+ Status = ShellOpenFileByName (

+ mLocalFilePath,

+ &mFileHandle,

+ EFI_FILE_MODE_CREATE |

+ EFI_FILE_MODE_WRITE |

+ EFI_FILE_MODE_READ,

+ 0);

+ if (EFI_ERROR (Status)) {

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),

+ mHttpHiiHandle, HTTP_APP_NAME, mLocalFilePath

+ );

+ goto ON_EXIT;

+ }

+

+ do {

+ SHELL_FREE_NON_NULL (DownloadUrl);

+ UrlSize = 0;

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ Context->ServerAddrAndProto,

+ StrLen (Context->ServerAddrAndProto)

+ );

+ if (Context->URI[0] != L'/') {

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ L"/",

+ StrLen (Context->ServerAddrAndProto)

+ );

+ }

+

+ DownloadUrl = StrnCatGrow (

+ &DownloadUrl,

+ &UrlSize,

+ Context->URI,

+ StrLen (Context->URI));

+

+ ShellPrintHiiEx (

+ -1, -1, NULL, STRING_TOKEN (STR_HTTP_DOWNLOADING),

+ mHttpHiiHandle, DownloadUrl);

+

+ Status = SendRequest (Context, DownloadUrl);

+ if (Status) {

+ goto ON_EXIT;

+ }

+

+ Status = GetResponse (Context, DownloadUrl);

+

+ if (Status) {

+ goto ON_EXIT;

+ }

+

+ } while (Context->Status == REQ_NEED_REPEAT);

+

+ if (Context->Status) {

+ Status = ENCODE_ERROR (Context->Status);

+ }

+

+ON_EXIT:

+ //

+ // CLOSE FILE

+ //

+ if (mFileHandle) {

+ if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) {

+ ShellDeleteFile (&mFileHandle);

+ } else {

+ ShellCloseFile (&mFileHandle);

+ }

+ }

+

+ SHELL_FREE_NON_NULL (DownloadUrl);

+ SHELL_FREE_NON_NULL (Context->Buffer);

+

+ return Status;

+}

+

+/**

+ Retrive HII package list from ImageHandle and publish to HII
database.

+

+ @param ImageHandle The image handle of the process.

+

+ @return HII handle.

+**/

+EFI_HII_HANDLE

+InitializeHiiPackage (

+ EFI_HANDLE ImageHandle

+ )

+{

+ EFI_STATUS Status;

+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;

+ EFI_HII_HANDLE HiiHandle;

+

+ //

+ // Retrieve HII package list from ImageHandle

+ //

+ Status = gBS->OpenProtocol (

+ ImageHandle,

+ &gEfiHiiPackageListProtocolGuid,

+ (VOID **)&PackageList,

+ ImageHandle,

+ NULL,

+ EFI_OPEN_PROTOCOL_GET_PROTOCOL

+ );

+ ASSERT_EFI_ERROR (Status);

+ if (EFI_ERROR (Status)) {

+ return NULL;

+ }

+

+ //

+ // Publish HII package list to HII Database.

+ //

+ Status = gHiiDatabase->NewPackageList (

+ gHiiDatabase,

+ PackageList,

+ NULL,

+ &HiiHandle

+ );

+ ASSERT_EFI_ERROR (Status);

+ if (EFI_ERROR (Status)) {

+ return NULL;

+ }

+

+ return HiiHandle;

+}

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
new file mode 100644
index 000000000000..5c7b90e8cab4
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
@@ -0,0 +1,89 @@
+/** @file

+ Header file for 'http' command functions.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>

+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef _HTTP_H_

+#define _HTTP_H_

+

+#include <Uefi.h>

+

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DebugLib.h>

+#include <Library/HiiLib.h>

+#include <Library/HttpLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/NetLib.h>

+#include <Library/PrintLib.h>

+#include <Library/ShellLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiHiiServicesLib.h>

+#include <Library/UefiLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+

+#include <Protocol/HiiPackageList.h>

+#include <Protocol/HttpUtilities.h>

+#include <Protocol/ServiceBinding.h>

+

+#define HTTP_APP_NAME L"http"

+

+#define REQ_OK 0

+#define REQ_NEED_REPEAT 1

+

+// Download Flags

+#define DL_FLAG_TIME BIT0 // Show elapsed time.

+#define DL_FLAG_KEEP_BAD BIT1 // Keep files even if download failed.

+

+extern EFI_HII_HANDLE mHttpHiiHandle;

+

+typedef struct {

+ UINTN ContentDownloaded;

+ UINTN ContentLength;

+ UINTN LastReportedNbOfBytes;

+ UINTN BufferSize;

+ UINTN Status;

+ UINTN Flags;

+ UINT8 *Buffer;

+ CHAR16 *ServerAddrAndProto;

+ CHAR16 *URI;

+ EFI_HTTP_TOKEN ResponseToken;

+ EFI_HTTP_TOKEN RequestToken;

+ EFI_HTTP_PROTOCOL *Http;

+} DOWNLOAD_CONTEXT;

+

+/**

+ Function for 'http' command.

+

+ @param[in] ImageHandle The image handle.

+ @param[in] SystemTable The system table.

+

+ @retval SHELL_SUCCESS Command completed successfully.

+ @retval SHELL_INVALID_PARAMETER Command usage error.

+ @retval SHELL_ABORTED The user aborts the operation.

+ @retval value Unknown error.

+**/

+SHELL_STATUS

+RunHttp (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ );

+

+/**

+ Retrive HII package list from ImageHandle and publish to HII
database.

+

+ @param ImageHandle The image handle of the process.

+

+ @return HII handle.

+**/

+EFI_HII_HANDLE

+InitializeHiiPackage (

+ EFI_HANDLE ImageHandle

+ );

+#endif // _HTTP_H_

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
new file mode 100644
index 000000000000..00cf05deeb5c
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
@@ -0,0 +1,117 @@
+// /**

+//

+// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development
LP<BR>

+// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
<BR>

+// Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+// Module Name:

+//

+// Http.uni

+//

+// Abstract:

+//

+// String definitions for UEFI Shell HTTP command

+//

+//

+// **/

+

+/=#

+

+#langdef en-US "english"

+

+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too
many
arguments. Try help http.\r\n"

+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few
arguments. Try help http.\r\n"

+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid
argument - '%H%s%N'. Try help http.\r\n"

+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown
flag -
'%H%s%N'. Try help http.\r\n"

+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot
open
file - '%H%s%N'\r\n"

+#string STR_GEN_CRLF #language en-US "\r\n"

+

+#string STR_HTTP_ERR_NO_NIC #language en-US "No network
interface
card found.\r\n"

+#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the
name
of the network interface card number %d - %r\r\n"

+#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to
open
HTTP protocol on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to
configure
HTTP protocol on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to
download
the file '%H%s%N' on '%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_WRITE #language en-US "Unable to write
into
file
'%H%s%N' - %r\r\n"

+#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network
Interface
Card '%H%s%N' not found.\r\n"

+#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N'
reports
'%s' for '%H%s%N' \r\n"

+#string STR_HTTP_DOWNLOADING #language en-US "Downloading
'%H%s%N'\r\n"

+

+#string STR_GET_HELP_HTTP #language en-US ""

+".TH http 0 "Download a file from HTTP server."\r\n"

+".SH NAME\r\n"

+"Download a file from HTTP server.\r\n"

+".SH SYNOPSIS\r\n"

+" \r\n"

+"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n"

+" <URL> [localfilepath]\r\n"

+".SH OPTIONS\r\n"

+" \r\n"

+" -i interface - Specifies an adapter name, i.e., eth0.\r\n"

+" -k Keep the downloaded file even if there was an
error.\r\n"

+" If this parameter is not used, the file will be
deleted.\r\n"

+" -l port - Specifies the local port number. Default value
is 0\r\n"

+" and the port number is automatically
assigned.\r\n"

+" -m Measure and report download time (in seconds).
\r\n"

+" -s size The size of the download buffer for a chunk, in
bytes.\r\n"

+" Default is 32K. Note that larger buffer does
not imply\r\n"

+" better speed.\r\n"

+" -t timeout - The number of seconds to wait for completion
of\r\n"

+" requests and responses. Default is 0 which is
'automatic'.\r\n"

+" %HURL%N\r\n"

+" Two types of providing of URLs are supported:\r\n"

+" 1. tftp-like, where host and http_uri are separate
parameters\r\n"

+" (example: host /host_uri), and\r\n\"

+" 2. wget-like, where host and host_uri is one parameter.\r\n"

+" (example: host/host_uri)\r\n"

+"\r\n"

+" host - Specifies HTTP Server address.\r\n

+ Can be either IPv4 address or 'http (or
https)://addr'\r\n

+ Can use addresses resolvable by DNS as well.
\r\n

+ Port can be specified after ':' if needed.
\r\n

+ By default port 80 is used.\r\n"

+" http_uri - HTTP server URI to download the file.\r\n"

+"\r\n"

+" localfilepath - Local destination file path.\r\n"

+".SH DESCRIPTION\r\n"

+" \r\n"

+"NOTES:\r\n"

+" 1. The HTTP command allows geting of the file specified by its
'http_uri'\r\n"

+" path from the HTTP server specified by its 'host' IPv4 address.
If
the\r\n"

+" optional 'localfilepath' parameter is provided, the downloaded
file
is\r\n"

+" stored locally using the provided file path. If the local file
path is\r\n"

+" not specified, the file is stored in the current directory
using the
file\r\n"

+" server's name.\r\n"

+" 2. Before using the HTTP command, the network interface intended
to
be\r\n"

+" used to retrieve the file must be configured. This
configuration may
be\r\n"

+" done by means of the 'ifconfig' command.\r\n"

+" 3. If a network interface is defined with the '-i' option then
only
this\r\n"

+" interface will be used to retrieve the remote file. Otherwise,
all
network\r\n"

+" interfaces are tried in the order they have been discovered
during
the\r\n"

+" DXE phase.\r\n"

+".SH EXAMPLES\r\n"

+" \r\n"

+"EXAMPLES:\r\n"

+" * To get the file "dir1/file1.dat" from the HTTP server
192.168.1.1, port
8080,
and\r\n"

+" store it as file2.dat in the current directory (use tftp-like
URL format)
:\r\n"

+" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n"

+" * To get the file /image.bin via HTTPS from server 192.168.1.1 at
port 443
\r\n"

+" (default HTTPS port), and store it in the current directory:
\r\n"

+" fs0:\> http https://192.168.1.1 image.bin\r\n"

+" To get an index file from http://google.com and place it into
the \r\n"

+" current directory:\r\n"

+" fs0:\> http google.com index.html\r\n"

+".SH RETURNVALUES\r\n"

+" \r\n"

+"RETURN VALUES:\r\n"

+" SHELL_SUCCESS The action was completed as
requested.\r\n"

+" SHELL_INVALID_PARAMETER One of the passed-in parameters was
incorrectly\r\n"

+" formatted or its value was out of
bounds.\r\n"

+" HTTP_ERROR No EFI errors, but the server reported a
status
code\r\n"

+" which should be treated as an error. If
an error body
sent\r\n"

+" by the server, and -k parameter is on
command line,

+" the file wil be saved either as
localfilepath filename,\r\n"

+" or as an URI name in the current
directory.\r\n"

+" If '/' is at the end of the URL, and no
locafilepath
filename\r\n"

+" is given on the command line, the file
will be retrieved
as\r\n"

+" index.html.\r\n"

diff --git a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
new file mode 100644
index 000000000000..7bd5b46d3997
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
@@ -0,0 +1,53 @@
+/** @file

+ Entrypoint of "http" shell standalone application.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>

+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include "Http.h"

+

+/*

+ * String token ID of help message text.

+ * Shell supports to find help message in the resource section of an

+ * application image if * .MAN file is not found.

+ * This global variable is added to make build tool recognizes

+ * that the help string is consumed by user and then build tool will

+ * add the string into the resource section.

+ * Thus the application can use '-?' option to show help message in
Shell.

+ */

+GLOBAL_REMOVE_IF_UNREFERENCED

+EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN
(STR_GET_HELP_HTTP);

+

+/**

+ Entry point of Http standalone application.

+

+ @param ImageHandle The image handle of the process.

+ @param SystemTable The EFI System Table pointer.

+

+ @retval EFI_SUCCESS Http command is executed sucessfully.

+ @retval EFI_ABORTED HII package was failed to initialize.

+ @retval others Other errors when executing http
command.

+**/

+EFI_STATUS

+EFIAPI

+HttpAppInitialize (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);

+ if (mHttpHiiHandle == NULL) {

+ return EFI_ABORTED;

+ }

+

+ Status = (EFI_STATUS)RunHttp (ImageHandle, SystemTable);

+

+ HiiRemovePackages (mHttpHiiHandle);

+

+ return Status;

+}

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
new file mode 100644
index 000000000000..d08d47fb37d5
--- /dev/null
+++ b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
@@ -0,0 +1,58 @@
+## @file

+# Provides Shell 'http' standalone application.

+#

+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>

+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010006

+ BASE_NAME = http

+ FILE_GUID =
56B00FB7-91D2-869B-CE5C-26CD1A89C73C

+ MODULE_TYPE = UEFI_APPLICATION

+ VERSION_STRING = 1.0

+ ENTRY_POINT = HttpAppInitialize

+#

+# This flag specifies whether HII resource section is generated into
PE
image.

+#

+ UEFI_HII_RESOURCE_SECTION = TRUE

+

+[Sources.common]

+ Http.c

+ HttpApp.c

+ Http.h

+ Http.uni

+

+[Packages]

+ EmbeddedPkg/EmbeddedPkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ MdePkg/MdePkg.dec

+ NetworkPkg/NetworkPkg.dec

+ ShellPkg/ShellPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ BaseMemoryLib

+ DebugLib

+ FileHandleLib

+ HiiLib

+ HttpLib

+ MemoryAllocationLib

+ NetLib

+ ShellLib

+ UefiApplicationEntryPoint

+ UefiBootServicesTableLib

+ UefiHiiServicesLib

+ UefiLib

+ UefiRuntimeServicesTableLib

+

+[Protocols]

+ gEfiHiiPackageListProtocolGuid ## CONSUMES

+ gEfiHttpProtocolGuid ## CONSUMES

+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES

+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
new file mode 100644
index 000000000000..ba654749a075
--- /dev/null
+++
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.c
@@ -0,0 +1,134 @@
+/** @file

+ Produce "http" shell dynamic command.

+

+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.
<BR>

+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+#include <Protocol/ShellDynamicCommand.h>

+#include "Http.h"

+

+/**

+ This is the shell command handler function pointer callback type.
This

+ function handles the command when it is invoked in the shell.

+

+ @param[in] This The instance of the

+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+ @param[in] SystemTable The pointer to the system table.

+ @param[in] ShellParameters The parameters associated with the
command.

+ @param[in] Shell The instance of the shell protocol
used in

+ the context of processing this
command.

+

+ @return EFI_SUCCESS the operation was sucessful

+ @return other the operation failed.

+**/

+SHELL_STATUS

+EFIAPI

+HttpCommandHandler (

+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,

+ IN EFI_SYSTEM_TABLE *SystemTable,

+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,

+ IN EFI_SHELL_PROTOCOL *Shell

+ )

+{

+ gEfiShellParametersProtocol = ShellParameters;

+ gEfiShellProtocol = Shell;

+

+ return RunHttp (gImageHandle, SystemTable);

+}

+

+/**

+ This is the command help handler function pointer callback type.
This

+ function is responsible for displaying help information for the
associated

+ command.

+

+ @param[in] This The instance of the
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.

+ @param[in] Language The pointer to the language string to use.

+

+ @return string Pool allocated help string, must be freed by
caller

+**/

+CHAR16 *

+EFIAPI

+HttpCommandGetHelp (

+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,

+ IN CONST CHAR8 *Language

+ )

+{

+ return HiiGetString(mHttpHiiHandle,

+ STRING_TOKEN (STR_GET_HELP_HTTP),

+ Language);

+}

+

+EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand
= {

+ HTTP_APP_NAME,

+ HttpCommandHandler,

+ HttpCommandGetHelp

+};

+

+/**

+ Entry point of Http Dynamic Command.

+

+ Produce the DynamicCommand protocol to handle "http" command.

+

+ @param ImageHandle The image handle of the process.

+ @param SystemTable The EFI System Table pointer.

+

+ @retval EFI_SUCCESS Http command is executed sucessfully.

+ @retval EFI_ABORTED HII package was failed to initialize.

+ @retval others Other errors when executing http
command.

+**/

+EFI_STATUS

+EFIAPI

+HttpCommandInitialize (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+

+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);

+ if (mHttpHiiHandle == NULL) {

+ return EFI_ABORTED;

+ }

+

+ Status = gBS->InstallProtocolInterface (

+ &ImageHandle,

+ &gEfiShellDynamicCommandProtocolGuid,

+ EFI_NATIVE_INTERFACE,

+ &mHttpDynamicCommand

+ );

+ ASSERT_EFI_ERROR (Status);

+ return Status;

+}

+

+/**

+ Http driver unload handler.

+

+ @param ImageHandle The image handle of the process.

+

+ @retval EFI_SUCCESS The image is unloaded.

+ @retval Others Failed to unload the image.

+**/

+EFI_STATUS

+EFIAPI

+HttpUnload (

+ IN EFI_HANDLE ImageHandle

+)

+{

+ EFI_STATUS Status;

+ Status = gBS->UninstallProtocolInterface (

+ ImageHandle,

+ &gEfiShellDynamicCommandProtocolGuid,

+ &mHttpDynamicCommand

+ );

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ HiiRemovePackages (mHttpHiiHandle);

+

+ return EFI_SUCCESS;

+}

diff --git
a/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
new file mode 100644
index 000000000000..5d46ee2384d5
--- /dev/null
+++
b/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicComma
nd.in
f
@@ -0,0 +1,63 @@
+## @file

+# Provides Shell 'http' dynamic command.

+#

+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
<BR>

+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>

+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010006

+ BASE_NAME = httpDynamicCommand

+ FILE_GUID =
19618BCE-55AE-09C6-37E9-4CE04084C7A1

+ MODULE_TYPE = DXE_DRIVER

+ VERSION_STRING = 1.0

+ ENTRY_POINT = HttpCommandInitialize

+ UNLOAD_IMAGE = HttpUnload

+#

+# This flag specifies whether HII resource section is generated into
PE
image.

+#

+ UEFI_HII_RESOURCE_SECTION = TRUE

+

+[Sources.common]

+ Http.c

+ HttpDynamicCommand.c

+ Http.h

+ Http.uni

+

+[Packages]

+ EmbeddedPkg/EmbeddedPkg.dec

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ NetworkPkg/NetworkPkg.dec

+ ShellPkg/ShellPkg.dec

+

+[LibraryClasses]

+ BaseLib

+ BaseMemoryLib

+ DebugLib

+ FileHandleLib

+ HiiLib

+ HttpLib

+ MemoryAllocationLib

+ NetLib

+ ShellLib

+ UefiBootServicesTableLib

+ UefiDriverEntryPoint

+ UefiHiiServicesLib

+ UefiLib

+ UefiRuntimeServicesTableLib

+

+[Protocols]

+ gEfiHiiPackageListProtocolGuid ## CONSUMES

+ gEfiHttpProtocolGuid ## CONSUMES

+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES

+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES

+ gEfiShellDynamicCommandProtocolGuid ## PRODUCES

+

+[DEPEX]

+ TRUE

diff --git a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index 5da9128333a4..6e328b460d8c 100644
--- a/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -59,6 +59,10 @@
0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2,
0x0e,
0xd4 }
\

}



+#define SHELL_HTTP_HII_GUID \

+ { \

+ 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e,
0x0a,
0x7e } \

+ }



#define SHELL_BCFG_HII_GUID \

{ \

@@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;

extern EFI_GUID gShellNetwork2HiiGuid;

extern EFI_GUID gShellTftpHiiGuid;

+extern EFI_GUID gShellHttpHiiGuid;

extern EFI_GUID gShellBcfgHiiGuid;



#endif

diff --git a/ShellPkg/ShellPkg.dec b/ShellPkg/ShellPkg.dec
index d0843d338126..7b2d1230bd2c 100644
--- a/ShellPkg/ShellPkg.dec
+++ b/ShellPkg/ShellPkg.dec
@@ -53,6 +53,7 @@ [Guids]
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8,
{0xb0, 0xb7,
0xfa,
0x99, 0x9c, 0x62, 0x37, 0xae}}

gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12,
{0xaa, 0x60,
0x59,
0xdf, 0xf8, 0xd6, 0xea, 0x37}}

gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592,
{0x8f, 0xf7, 0xc1,
0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}

+ gShellHttpHiiGuid = {0x390f84b3, 0x221c, 0x4d9e,
{0xb5, 0x06,
0x6d,
0xb9, 0x42, 0x3e, 0x0a, 0x7e}}

gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d,
{0xa6, 0xb2, 0xeb,
0x12, 0xda, 0xb4, 0xa2, 0xb6}}

gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc,
{0xb5, 0xef,
0x2e,
0xf5, 0x5e, 0x24, 0x93, 0x2a}}

# FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf

diff --git a/ShellPkg/ShellPkg.dsc b/ShellPkg/ShellPkg.dsc
index 86e9f1e0040d..c42bc9464a0f 100644
--- a/ShellPkg/ShellPkg.dsc
+++ b/ShellPkg/ShellPkg.dsc
@@ -139,6 +139,11 @@ [Components]
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

}

ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf

+
ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand
.inf {

+ <PcdsFixedAtBuild>

+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

+ }

+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf

ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf
{

<PcdsFixedAtBuild>

gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE

--
2.26.2.266.ge870325ee8


Re: [PATCH 0/3] Platform/RasberryPi: Thermal zone

Ard Biesheuvel
 

On 8/14/20 1:00 AM, Jeremy Linton wrote:
This set creates a basic thermal zone, which reads the
SOC temp via a direct register read in AML. It also
adds an active cooling policy using a GPIO pin for fan
control that can optionally be enabled/disabled by the
user from the BDS.
With the fan enabled it should be possible to see the
soc temp like:
# sensors
acpitz-acpi-0
Adapter: ACPI interface
temp1: +57.6C (crit = +90.0C)
and the fan state may be read/cycled with:
/sys/bus/acpi/devices/PNP0C06:00/PNP0C0B:00/physical_node/thermal_cooling/cur_state
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
Jeremy Linton (3):
Platform/RaspberryPi4: Add a basic thermal zone
Platform/RaspberryPi4: Create ACPI fan object
Platform/RaspberryPi: Add entry for user fan control
I like this code a lot. It is very helpful to have working sample AML code that implements a thermal zone. Could you elaborate on the additional components that are needed for this? Is this a standard cape (or whatever rpi calls it)? I assume the fan just switches between 0 and max rpm depending on the actual temp wrt the trip point?



Platform/RaspberryPi/AcpiTables/Dsdt.asl | 31 ++++++++
Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c | 55 ++++++++++++++
.../RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf | 3 +
.../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni | 5 ++
.../RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr | 17 +++++
.../RaspberryPi/Drivers/ConfigDxe/SsdtThermal.asl | 83 ++++++++++++++++++++++
Platform/RaspberryPi/Include/ConfigVars.h | 4 ++
Platform/RaspberryPi/RPi3/RPi3.dsc | 5 ++
Platform/RaspberryPi/RPi4/RPi4.dsc | 8 +++
Platform/RaspberryPi/RaspberryPi.dec | 1 +
.../Bcm27xx/Include/IndustryStandard/Bcm2711.h | 2 +
11 files changed, 214 insertions(+)
create mode 100644 Platform/RaspberryPi/Drivers/ConfigDxe/SsdtThermal.asl


Re: [edk2-platform][PATCH v1 1/3] Platforms/RaspberryPi: Fix DisplayDxe ComponentName2 error checking

Samer El-Haj-Mahmoud
 

Thanks Ard and Pete.

I did use the cover letter, but forgot to add the CC https://edk2.groups.io/g/devel/message/64301

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ard
Biesheuvel via groups.io
Sent: Monday, August 17, 2020 9:55 AM
To: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>;
devel@edk2.groups.io
Cc: Leif Lindholm <leif@nuviainc.com>; Pete Batard <pete@akeo.ie>; Andrei
Warkentin (awarkentin@vmware.com) <awarkentin@vmware.com>
Subject: Re: [edk2-devel] [edk2-platform][PATCH v1 1/3]
Platforms/RaspberryPi: Fix DisplayDxe ComponentName2 error checking

On 8/15/20 10:26 PM, Samer El-Haj-Mahmoud wrote:
Fix input param error checking for the DisplayDxe ComponentName2
protocol.

This fixes https://github.com/pftf/RPi4/issues/84

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
---
Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h | 2 ++
Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c | 22
++++++++++++++++++++
2 files changed, 24 insertions(+)
Please use a cover letter for multipatch series.

Series pushed as c475b1bbda25..69009e5b91a7 (with Pete's comments
addressed)

Thanks,

diff --git a/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
b/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
index bfbe9e868843..073f65111645 100644
--- a/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
+++ b/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2017-2018, Andrei Warkentin
<andrey.warkentin@gmail.com>
* Copyright (c) Microsoft Corporation. All rights reserved.
*
@@ -27,6 +28,7 @@
extern EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto;
extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL mDriverBinding;

VOID
RegisterScreenshotHandlers (
diff --git a/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
b/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
index 092230cd7c9b..4c065b5d51bf 100644
--- a/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
+++ b/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
* Copyright (c) 2006-2016, Intel Corporation. All rights reserved.
*
@@ -206,6 +207,27 @@ ComponentNameGetControllerName (
OUT CHAR16 **ControllerName
)
{
+ EFI_STATUS Status;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllHandle //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ mDriverBinding.DriverBindingHandle,
+ &gEfiGraphicsOutputProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,

IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.


Re: [edk2-platform][PATCH v1 1/3] Platforms/RaspberryPi: Fix DisplayDxe ComponentName2 error checking

Ard Biesheuvel
 

On 8/15/20 10:26 PM, Samer El-Haj-Mahmoud wrote:
Fix input param error checking for the DisplayDxe ComponentName2
protocol.
This fixes https://github.com/pftf/RPi4/issues/84
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
---
Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h | 2 ++
Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c | 22 ++++++++++++++++++++
2 files changed, 24 insertions(+)
Please use a cover letter for multipatch series.

Series pushed as c475b1bbda25..69009e5b91a7 (with Pete's comments addressed)

Thanks,

diff --git a/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h b/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
index bfbe9e868843..073f65111645 100644
--- a/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
+++ b/Platform/RaspberryPi/Drivers/DisplayDxe/DisplayDxe.h
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
* Copyright (c) Microsoft Corporation. All rights reserved.
*
@@ -27,6 +28,7 @@
extern EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto;
extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL mDriverBinding;
VOID
RegisterScreenshotHandlers (
diff --git a/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c b/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
index 092230cd7c9b..4c065b5d51bf 100644
--- a/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
+++ b/Platform/RaspberryPi/Drivers/DisplayDxe/ComponentName.c
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2018, Andrei Warkentin <andrey.warkentin@gmail.com>
* Copyright (c) 2006-2016, Intel Corporation. All rights reserved.
*
@@ -206,6 +207,27 @@ ComponentNameGetControllerName (
OUT CHAR16 **ControllerName
)
{
+ EFI_STATUS Status;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ mDriverBinding.DriverBindingHandle,
+ &gEfiGraphicsOutputProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,


Re: [edk2-platform][PATCH v1 3/3] Platforms/RaspberryPi: Fix BcmGenetDxe ComponentName2 error checking

Pete Batard
 

Same typo as previous patch:

On 2020.08.15 21:26, Samer El-Haj-Mahmoud wrote:
Fix input param error checking for the BcmGenetDxe ComponentName2
protocol.
This fixes https://github.com/pftf/RPi4/issues/85
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
---
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.h | 1 +
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c | 22 ++++++++++++++++++++
Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c | 2 +-
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.h b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.h
index b39a1326335a..26016330fb3b 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.h
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/BcmGenetDxe.h
@@ -235,6 +235,7 @@ typedef struct {
extern EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL mGenetDriverBinding;
extern CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate;
extern CONST EFI_ADAPTER_INFORMATION_PROTOCOL gGenetAdapterInfoTemplate;
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
index 860e30b4da6b..abc5b7db16c2 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/ComponentName.c
@@ -2,6 +2,7 @@
UEFI Component Name(2) protocol implementation for GENET UEFI driver.
Copyright (c) 2020 Jared McNeill. All rights reserved.
+ Copyright (c) 2020, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -169,6 +170,27 @@ GenetComponentNameGetControllerName (
OUT CHAR16 **ControllerName
)
{
+ EFI_STATUS Status;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Make sure this driver is currently managing ControllHandle
Shouldn't it be 'ControllerHandle' rather than 'ControllHandle'?

+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ mGenetDriverBinding.DriverBindingHandle,
+ &gEfiSimpleNetworkProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
diff --git a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
index f9aa006dc799..435ef493564c 100644
--- a/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
+++ b/Silicon/Broadcom/Drivers/Net/BcmGenetDxe/DriverBinding.c
@@ -302,7 +302,7 @@ GenetDriverBindingStop (
return EFI_SUCCESS;
}
-STATIC EFI_DRIVER_BINDING_PROTOCOL mGenetDriverBinding = {
+EFI_DRIVER_BINDING_PROTOCOL mGenetDriverBinding = {
GenetDriverBindingSupported,
GenetDriverBindingStart,
GenetDriverBindingStop,
Reviewed-by: Pete Batard <pete@akeo.ie>


Re: [edk2-platform][PATCH v1 2/3] Platforms/RaspberryPi: Fix DwUsbHostDxe ComponentName2 error checking

Pete Batard
 

Same typo as previous patch:

On 2020.08.15 21:26, Samer El-Haj-Mahmoud wrote:
Fix input param error checking for the DwUsbHostDxe ComponentName2
protocol.
This fixes https://github.com/pftf/RPi4/issues/86
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Pete Batard <pete@akeo.ie>
Cc: Andrei Warkentin <awarkentin@vmware.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
---
Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwUsbHostDxe.h | 4 +++-
Platform/RaspberryPi/Drivers/DwUsbHostDxe/ComponentName.c | 18 ++++++++++++++++++
Platform/RaspberryPi/Drivers/DwUsbHostDxe/DriverBinding.c | 2 +-
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwUsbHostDxe.h b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwUsbHostDxe.h
index 106e5425355e..cf6c81b64ab5 100644
--- a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwUsbHostDxe.h
+++ b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwUsbHostDxe.h
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2017-2018, Andrey Warkentin <andrey.warkentin@gmail.com>
* Copyright (c) 2015-2016, Linaro Limited. All rights reserved.
*
@@ -121,8 +122,9 @@ typedef struct _DWUSB_OTGHC_DEV {
UINT16 LastMicroFrame;
} DWUSB_OTGHC_DEV;
-extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+extern EFI_COMPONENT_NAME_PROTOCOL gComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL mDriverBinding;
EFI_STATUS
CreateDwUsbHc (
diff --git a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/ComponentName.c b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/ComponentName.c
index 2f3c53323bf1..8639ab7d39c5 100644
--- a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/ComponentName.c
+++ b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/ComponentName.c
@@ -1,5 +1,6 @@
/** @file
*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
* Copyright (c) 2018, Andrey Warkentin <andrey.warkentin@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -205,10 +206,27 @@ ComponentNameGetControllerName (
OUT CHAR16 **ControllerName
)
{
+ EFI_STATUS Status;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
if (ChildHandle != NULL) {
return EFI_UNSUPPORTED;
}
+ //
+ // Make sure this driver is currently managing ControllHandle
Shouldn't it be 'ControllerHandle' rather than 'ControllHandle'?

+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ mDriverBinding.DriverBindingHandle,
+ &gEfiUsb2HcProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
diff --git a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DriverBinding.c b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DriverBinding.c
index 7f78179d4c06..bada13a6cd7c 100644
--- a/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DriverBinding.c
+++ b/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DriverBinding.c
@@ -36,7 +36,7 @@ DriverStop (
IN EFI_HANDLE *ChildHandleBuffer
);
-STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
+EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
DriverSupported,
DriverStart,
DriverStop,
Reviewed-by: Pete Batard <pete@akeo.ie>

10581 - 10600 of 74871