hikey: Add UEFI sources for reference

UEFI needs to be built outside Android build system.
Please follow the instructions in README.

The sources correspond to:
https://github.com/96boards/edk2/commit/14eae0c12e71fd33c4c0fc51e4475e8db02566cf
https://github.com/96boards/arm-trusted-firmware/commit/e9b4909dcd75fc4ae7041cfb83d28ab9adb7afdf
https://github.com/96boards/l-loader/commit/6b784ad5c4ab00e2b1c6f53cd5f74054e5d00a78
https://git.linaro.org/uefi/uefi-tools.git/commit/abe618f8ab72034fff1ce46c9c006a2c6bd40a7e

Change-Id: Ieeefdb63e673e0c8e64e0a1f02c7bddc63b2c7fb
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.c b/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.c
new file mode 100644
index 0000000..425109a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.c
@@ -0,0 +1,212 @@
+/*++ @file

+  Reset Architectural Protocol implementation.

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+--*/

+

+#include <PiDxe.h>

+

+#include <Protocol/Reset.h>

+

+#include <Guid/AcpiDescription.h>

+

+#include <Library/BaseLib.h>

+#include <Library/IoLib.h>

+#include <Library/PciLib.h>

+#include <Library/HobLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+

+///

+/// Handle for the Reset Architectural Protocol

+///

+EFI_HANDLE            mResetHandle = NULL;

+

+///

+/// Copy of ACPI Description HOB in runtime memory

+///

+EFI_ACPI_DESCRIPTION  mAcpiDescription;

+

+/**

+  Reset the system.

+

+  @param[in] ResetType       Warm or cold

+  @param[in] ResetStatus     Possible cause of reset

+  @param[in] DataSize        Size of ResetData in bytes

+  @param[in] ResetData       Optional Unicode string

+

+**/

+VOID

+EFIAPI

+EfiAcpiResetSystem (

+  IN EFI_RESET_TYPE   ResetType,

+  IN EFI_STATUS       ResetStatus,

+  IN UINTN            DataSize,

+  IN VOID             *ResetData OPTIONAL

+  )

+{

+  UINT8   Dev;

+  UINT8   Func;

+  UINT8   Register;

+  

+  switch (ResetType) {

+  case EfiResetShutdown:

+    //

+    // 1. Write SLP_TYPa

+    //

+    if ((mAcpiDescription.PM1a_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPa != 0)) {

+      switch (mAcpiDescription.PM1a_CNT_BLK.AddressSpaceId) {

+      case EFI_ACPI_3_0_SYSTEM_IO:

+        IoAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10)));

+        break;

+      case EFI_ACPI_3_0_SYSTEM_MEMORY:

+        MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10)));

+        break;

+      }

+    }

+

+    //

+    // 2. Write SLP_TYPb

+    //

+    if ((mAcpiDescription.PM1b_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPb != 0)) {

+      switch (mAcpiDescription.PM1b_CNT_BLK.AddressSpaceId) {

+      case EFI_ACPI_3_0_SYSTEM_IO:

+        IoAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10)));

+        break;

+      case EFI_ACPI_3_0_SYSTEM_MEMORY:

+        MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10)));

+        break;

+      }

+    }

+    //

+    // If Shutdown fails, then let fall through to reset 

+    //

+  case EfiResetWarm:

+  case EfiResetCold:

+    if ((mAcpiDescription.RESET_REG.Address != 0) &&

+        ((mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_IO) ||

+         (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_MEMORY) ||

+         (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE))) {

+      //

+      // Use ACPI System Reset

+      //

+      switch (mAcpiDescription.RESET_REG.AddressSpaceId) {

+      case EFI_ACPI_3_0_SYSTEM_IO:

+        //

+        // Send reset request through I/O port register

+        //

+        IoWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE);

+        //

+        // Halt 

+        //

+        CpuDeadLoop ();

+      case EFI_ACPI_3_0_SYSTEM_MEMORY:

+        //

+        // Send reset request through MMIO register

+        //

+        MmioWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE);

+        //

+        // Halt 

+        //

+        CpuDeadLoop ();

+      case EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE:

+        //

+        // Send reset request through PCI register

+        //

+        Register = (UINT8)mAcpiDescription.RESET_REG.Address;

+        Func     = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 16) & 0x7);

+        Dev      = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 32) & 0x1F);

+        PciWrite8 (PCI_LIB_ADDRESS (0, Dev, Func, Register), mAcpiDescription.RESET_VALUE);

+        //

+        // Halt 

+        //

+        CpuDeadLoop ();

+      }

+    }

+

+    //

+    // If system comes here, means ACPI reset is not supported, so do Legacy System Reset, assume 8042 available

+    //

+    IoWrite8 (0x64, 0xfe);

+    CpuDeadLoop ();

+

+  default:

+    break;

+  }

+

+  //

+  // Given we should have reset getting here would be bad

+  //

+  ASSERT (FALSE);

+  CpuDeadLoop();

+}

+

+/**

+  Initialize the state information for the Reset Architectural Protocol.

+

+  @param[in] ImageHandle  Image handle of the loaded driver

+  @param[in] SystemTable  Pointer to the System Table

+

+  @retval EFI_SUCCESS           Thread can be successfully created

+  @retval EFI_UNSUPPORTED       Cannot find the info to reset system

+

+**/

+EFI_STATUS

+EFIAPI

+InitializeReset (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS         Status;

+  EFI_HOB_GUID_TYPE  *HobAcpiDescription;

+

+  //

+  // Make sure the Reset Architectural Protocol is not already installed in the system

+  //

+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);

+

+  //

+  // Get ACPI Description HOB

+  //

+  HobAcpiDescription = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);

+  if (HobAcpiDescription == NULL) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Copy it to Runtime Memory

+  //

+  ASSERT (sizeof (EFI_ACPI_DESCRIPTION) == GET_GUID_HOB_DATA_SIZE (HobAcpiDescription));

+  CopyMem (&mAcpiDescription, GET_GUID_HOB_DATA (HobAcpiDescription), sizeof (EFI_ACPI_DESCRIPTION));

+

+  DEBUG ((DEBUG_INFO, "ACPI Reset Base  - %lx\n", mAcpiDescription.RESET_REG.Address));

+  DEBUG ((DEBUG_INFO, "ACPI Reset Value - %02x\n", (UINTN)mAcpiDescription.RESET_VALUE));

+  DEBUG ((DEBUG_INFO, "IAPC support     - %x\n", (UINTN)(mAcpiDescription.IAPC_BOOT_ARCH)));

+  

+  //

+  // Hook the runtime service table

+  //

+  SystemTable->RuntimeServices->ResetSystem = EfiAcpiResetSystem;

+

+  //

+  // Install the Reset Architectural Protocol onto a new handle

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &mResetHandle,

+                  &gEfiResetArchProtocolGuid, NULL,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.inf b/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.inf
new file mode 100644
index 0000000..591bdcf
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/AcpiResetDxe/Reset.inf
@@ -0,0 +1,47 @@
+## @file

+#  Component description file for AcpiResetDxe module.

+#

+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#

+##

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = AcpiReset

+  FILE_GUID                      = 928EF6D4-72BC-4686-B57B-1EEB6ABD4F93

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = InitializeReset

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[LibraryClasses]

+  DebugLib

+  UefiBootServicesTableLib

+  UefiDriverEntryPoint

+  IoLib

+  PciLib

+  HobLib

+  BaseLib

+  BaseMemoryLib

+

+[Sources]

+  Reset.c

+

+[Protocols]

+  gEfiResetArchProtocolGuid

+

+[Guids]

+  gEfiAcpiDescriptionGuid

+

+[Depex]

+  TRUE

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.c b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.c
new file mode 100644
index 0000000..da2c877
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.c
@@ -0,0 +1,2822 @@
+/** @file

+

+  BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom.

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#include "BiosVideo.h"

+

+//

+// EFI Driver Binding Protocol Instance

+//

+EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding = {

+  BiosVideoDriverBindingSupported,

+  BiosVideoDriverBindingStart,

+  BiosVideoDriverBindingStop,

+  0x3,

+  NULL,

+  NULL

+};

+

+//

+// Global lookup tables for VGA graphics modes

+//

+UINT8 mVgaLeftMaskTable[]   = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };

+

+UINT8 mVgaRightMaskTable[]  = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };

+

+UINT8 mVgaBitMaskTable[]    = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };

+

+EFI_LEGACY_8259_PROTOCOL   *mLegacy8259 = NULL;

+THUNK_CONTEXT              mThunkContext;

+

+EFI_GRAPHICS_OUTPUT_BLT_PIXEL  mVgaColorToGraphicsOutputColor[] = {

+  //

+  // {B, G, R, reserved}

+  //  

+  {0x00, 0x00, 0x00, 0x00}, // BLACK

+  {0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE

+  {0x00, 0x98, 0x00, 0x00}, // LIGHGREEN

+  {0x98, 0x98, 0x00, 0x00}, // LIGHCYAN

+  {0x00, 0x00, 0x98, 0x00}, // LIGHRED

+  {0x98, 0x00, 0x98, 0x00}, // MAGENTA

+  {0x00, 0x98, 0x98, 0x00}, // BROWN

+  {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY

+  {0x10, 0x10, 0x10, 0x00},

+  {0xff, 0x10, 0x10, 0x00}, // BLUE

+  {0x10, 0xff, 0x10, 0x00}, // LIME

+  {0xff, 0xff, 0x10, 0x00}, // CYAN

+  {0x10, 0x10, 0xff, 0x00}, // RED

+  {0xf0, 0x10, 0xff, 0x00}, // FUCHSIA

+  {0x10, 0xff, 0xff, 0x00}, // YELLOW

+  {0xff, 0xff, 0xff, 0x00}  // WHITE  

+};

+

+//

+// Standard timing defined by VESA EDID

+//

+VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming[] = {

+  //

+  // Established Timing I

+  //

+  {800, 600, 60},

+  {800, 600, 56},

+  {640, 480, 75},

+  {640, 480, 72},

+  {640, 480, 67},

+  {640, 480, 60},

+  {720, 400, 88},

+  {720, 400, 70},

+  //

+  // Established Timing II

+  //

+  {1280, 1024, 75},

+  {1024,  768, 75},

+  {1024,  768, 70},

+  {1024,  768, 60},

+  {1024,  768, 87},

+  {832,   624, 75},

+  {800,   600, 75},

+  {800,   600, 72},

+  //

+  // Established Timing III

+  //

+  {1152, 870, 75}

+};

+

+/**

+  Install child hanlde for a detect BiosVideo device and install related protocol

+  into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.

+

+  @param This                Instance pointer of EFI_DRIVER_BINDING_PROTOCOL

+  @param ParentHandle        Parent's controller handle

+  @param ParentPciIo         Parent's EFI_PCI_IO_PROTOCOL instance pointer

+  @param ParentLegacy8259    Parent's EFI_LEGACY_8259_PROTOCOL instance pointer 

+  @param ParentDevicePath    Parent's BIOS Video controller device path

+  @param RemainingDevicePath Remaining device path node instance for children.

+

+  @return whether success to create children handle for a VGA device and install 

+          related protocol into new children handle.

+

+**/

+EFI_STATUS

+BiosVideoChildHandleInstall (

+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN  EFI_HANDLE                     ParentHandle,

+  IN  EFI_PCI_IO_PROTOCOL            *ParentPciIo,

+  IN  EFI_LEGACY_8259_PROTOCOL       *ParentLegacy8259,

+  IN  THUNK_CONTEXT                  *ThunkContext,

+  IN  EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath,

+  IN  EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+;

+

+/**

+  Deregister an video child handle and free resources

+

+  @param This            Protocol instance pointer.

+  @param Controller      Video controller handle

+  @param Handle          Video child handle

+

+  @return EFI_STATUS

+

+**/

+

+EFI_STATUS

+BiosVideoChildHandleUninstall (

+  EFI_DRIVER_BINDING_PROTOCOL    *This,

+  EFI_HANDLE                     Controller,

+  EFI_HANDLE                     Handle

+  )

+;

+

+/**

+  Collect the resource from destroyed bios video device.

+

+  @param BiosVideoPrivate   Video child device private data structure

+**/

+

+VOID

+BiosVideoDeviceReleaseResource (

+  BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+;

+

+/**

+  Driver Entry Point.

+

+  @param ImageHandle      Handle of driver image.

+  @param SystemTable      Pointer to system table.

+

+  @return EFI_STATUS

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverEntryPoint (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+

+  Status = EfiLibInstallDriverBindingComponentName2 (

+            ImageHandle,

+            SystemTable,

+            &gBiosVideoDriverBinding,

+            ImageHandle,

+            &gBiosVideoComponentName,

+            &gBiosVideoComponentName2

+            );

+            

+  return Status;

+}

+

+/**

+  Test to see if Bios Video could be supported on the Controller.

+

+  @param This                  Pointer to driver binding protocol

+  @param Controller            Controller handle to connect

+  @param RemainingDevicePath   A pointer to the remaining portion of a device path

+

+  @retval EFI_SUCCESS         This driver supports this device.

+  @retval other               This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+{

+  EFI_STATUS                Status;

+  EFI_LEGACY_8259_PROTOCOL  *LegacyBios;

+  EFI_PCI_IO_PROTOCOL       *PciIo;

+

+  //

+  // See if the Legacy 8259 Protocol is available

+  //

+  Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &LegacyBios);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  //

+  // Open the IO Abstraction(s) needed to perform the supported test

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  if (!BiosVideoIsVga (PciIo)) {

+    Status = EFI_UNSUPPORTED;

+  }

+

+  gBS->CloseProtocol (

+         Controller,

+         &gEfiPciIoProtocolGuid,

+         This->DriverBindingHandle,

+         Controller

+         );

+

+  return Status;

+}

+

+/**

+  Install Graphics Output Protocol onto VGA device handles

+

+  @param This                   Pointer to driver binding protocol

+  @param Controller             Controller handle to connect

+  @param RemainingDevicePath    A pointer to the remaining portion of a device path

+

+  @return EFI_STATUS

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+{

+  EFI_STATUS                      Status;

+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;

+  EFI_PCI_IO_PROTOCOL             *PciIo;

+

+  PciIo = NULL;

+  //

+  // Prepare for status code

+  //

+  Status = gBS->HandleProtocol (

+                  Controller,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID **) &ParentDevicePath

+                  );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  //

+  // Open the IO Abstraction(s) needed

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  //

+  // Establish legacy environment for thunk call for all children handle.

+  //

+  if (mLegacy8259 == NULL) {

+    Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);

+    if (EFI_ERROR (Status)) {

+        goto Done;

+    }

+    

+    InitializeBiosIntCaller(&mThunkContext);

+    InitializeInterruptRedirection(mLegacy8259);

+  }

+

+  //

+  // Create child handle and install GraphicsOutputProtocol on it

+  //

+  Status = BiosVideoChildHandleInstall (

+             This,

+             Controller,

+             PciIo,

+             mLegacy8259,

+             &mThunkContext,

+             ParentDevicePath,

+             RemainingDevicePath

+             );

+

+Done:

+  if (EFI_ERROR (Status)) {

+    if (PciIo != NULL) {

+      //

+      // Release PCI I/O Protocols on the controller handle.

+      //

+      gBS->CloseProtocol (

+             Controller,

+             &gEfiPciIoProtocolGuid,

+             This->DriverBindingHandle,

+             Controller

+             );

+    }

+  }

+

+  return Status;

+}

+

+/**

+  Stop this driver on Controller 

+

+  @param  This              Protocol instance pointer.

+  @param  Controller        Handle of device to stop driver on

+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of

+                            children is zero stop the entire bus driver.

+  @param  ChildHandleBuffer List of Child Handles to Stop.

+

+  @retval EFI_SUCCESS       This driver is removed Controller.

+  @retval other             This driver was not removed from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,

+  IN  EFI_HANDLE                      Controller,

+  IN  UINTN                           NumberOfChildren,

+  IN  EFI_HANDLE                      *ChildHandleBuffer

+  )

+{

+  EFI_STATUS                   Status;

+  BOOLEAN                      AllChildrenStopped;

+  UINTN                        Index;

+

+  if (NumberOfChildren == 0) {

+    //

+    // Close PCI I/O protocol on the controller handle

+    //

+    gBS->CloseProtocol (

+           Controller,

+           &gEfiPciIoProtocolGuid,

+           This->DriverBindingHandle,

+           Controller

+           );

+

+    return EFI_SUCCESS;

+  }

+

+  AllChildrenStopped = TRUE;

+  for (Index = 0; Index < NumberOfChildren; Index++) {

+    Status = BiosVideoChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);

+

+    if (EFI_ERROR (Status)) {

+      AllChildrenStopped = FALSE;

+    }

+  }

+

+  if (!AllChildrenStopped) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Install child hanlde for a detect BiosVideo device and install related protocol

+  into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.

+

+  @param This                Instance pointer of EFI_DRIVER_BINDING_PROTOCOL

+  @param ParentHandle        Parent's controller handle

+  @param ParentPciIo         Parent's EFI_PCI_IO_PROTOCOL instance pointer

+  @param ParentLegacy8259    Parent's EFI_LEGACY_8259_PROTOCOL instance pointer 

+  @param ParentDevicePath    Parent's BIOS Video controller device path

+  @param RemainingDevicePath Remaining device path node instance for children.

+

+  @return whether success to create children handle for a VGA device and install 

+          related protocol into new children handle.

+

+**/

+EFI_STATUS

+BiosVideoChildHandleInstall (

+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN  EFI_HANDLE                     ParentHandle,

+  IN  EFI_PCI_IO_PROTOCOL            *ParentPciIo,

+  IN  EFI_LEGACY_8259_PROTOCOL       *ParentLegacy8259,

+  IN  THUNK_CONTEXT                  *ParentThunkContext,

+  IN  EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath,

+  IN  EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+{

+  EFI_STATUS               Status;

+  BIOS_VIDEO_DEV           *BiosVideoPrivate;

+  ACPI_ADR_DEVICE_PATH     AcpiDeviceNode;

+

+  //

+  // Allocate the private device structure for video device

+  //

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  sizeof (BIOS_VIDEO_DEV),

+                  (VOID**) &BiosVideoPrivate

+                  );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  ZeroMem (BiosVideoPrivate, sizeof (BIOS_VIDEO_DEV));

+

+  if (!BiosVideoIsVga (ParentPciIo)) {

+    Status = EFI_UNSUPPORTED;

+    goto Done;

+  }

+  

+  BiosVideoPrivate->VgaCompatible = TRUE;

+

+  //

+  // Initialize the child private structure

+  //

+  BiosVideoPrivate->Signature = BIOS_VIDEO_DEV_SIGNATURE;

+  BiosVideoPrivate->Handle    = NULL;

+

+  //

+  // Fill in Graphics Output specific mode structures

+  //

+  BiosVideoPrivate->HardwareNeedsStarting = TRUE;

+  BiosVideoPrivate->ModeData              = NULL;

+  BiosVideoPrivate->LineBuffer            = NULL;

+  BiosVideoPrivate->VgaFrameBuffer        = NULL;

+  BiosVideoPrivate->VbeFrameBuffer        = NULL;

+

+  //

+  // Fill in the VGA Mini Port Protocol fields

+  //

+  BiosVideoPrivate->VgaMiniPort.SetMode                   = BiosVideoVgaMiniPortSetMode;

+  BiosVideoPrivate->VgaMiniPort.VgaMemoryOffset           = 0xb8000;

+  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterOffset = 0x3d4;

+  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterOffset    = 0x3d5;

+  BiosVideoPrivate->VgaMiniPort.VgaMemoryBar              = EFI_PCI_IO_PASS_THROUGH_BAR;

+  BiosVideoPrivate->VgaMiniPort.CrtcAddressRegisterBar    = EFI_PCI_IO_PASS_THROUGH_BAR;

+  BiosVideoPrivate->VgaMiniPort.CrtcDataRegisterBar       = EFI_PCI_IO_PASS_THROUGH_BAR;

+

+  //

+  // Assume that Graphics Output Protocol will be produced until proven otherwise

+  //

+  BiosVideoPrivate->ProduceGraphicsOutput = TRUE;

+

+  //

+  // Child handle need to consume the Legacy Bios protocol

+  //

+  BiosVideoPrivate->Legacy8259   = ParentLegacy8259;

+  BiosVideoPrivate->ThunkContext = ParentThunkContext;

+  

+  //

+  // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally

+  //

+  BiosVideoPrivate->PciIo = ParentPciIo;

+

+  //

+  // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output

+  //

+  Status = BiosVideoCheckForVbe (BiosVideoPrivate);

+  if (EFI_ERROR (Status)) {

+    //

+    // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support

+    // for the standard 640x480 16 color VGA mode

+    //

+    if (BiosVideoPrivate->VgaCompatible) {

+      Status = BiosVideoCheckForVga (BiosVideoPrivate);

+    }

+

+    if (EFI_ERROR (Status)) {

+      //

+      // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do

+      // not produce the Graphics Output protocol.  Instead, produce the VGA MiniPort Protocol.

+      //

+      BiosVideoPrivate->ProduceGraphicsOutput = FALSE;

+

+      //

+      // INT services are available, so on the 80x25 and 80x50 text mode are supported

+      //

+      BiosVideoPrivate->VgaMiniPort.MaxMode = 2;

+    }

+  }

+

+  if (BiosVideoPrivate->ProduceGraphicsOutput) {

+    if (RemainingDevicePath == NULL) {

+      ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));

+      AcpiDeviceNode.Header.Type    = ACPI_DEVICE_PATH;

+      AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;

+      AcpiDeviceNode.ADR            = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);

+      SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));

+

+      BiosVideoPrivate->DevicePath = AppendDevicePathNode (

+                                       ParentDevicePath, 

+                                       (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode

+                                       );

+    } else {

+      BiosVideoPrivate->DevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);

+    }

+

+    //

+    // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol

+    //

+    Status = gBS->InstallMultipleProtocolInterfaces (

+                    &BiosVideoPrivate->Handle,

+                    &gEfiDevicePathProtocolGuid,

+                    BiosVideoPrivate->DevicePath,

+                    &gEfiGraphicsOutputProtocolGuid,

+                    &BiosVideoPrivate->GraphicsOutput,

+                    &gEfiEdidDiscoveredProtocolGuid,

+                    &BiosVideoPrivate->EdidDiscovered,

+                    &gEfiEdidActiveProtocolGuid,

+                    &BiosVideoPrivate->EdidActive,

+                    NULL

+                    );

+

+    if (!EFI_ERROR (Status)) {

+      //

+      // Open the Parent Handle for the child

+      //

+      Status = gBS->OpenProtocol (

+                      ParentHandle,

+                      &gEfiPciIoProtocolGuid,

+                      (VOID **) &BiosVideoPrivate->PciIo,

+                      This->DriverBindingHandle,

+                      BiosVideoPrivate->Handle,

+                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+                      );

+      if (EFI_ERROR (Status)) {

+        goto Done;

+      }

+    }

+  } else {

+    //

+    // Install VGA Mini Port Protocol

+    //

+    Status = gBS->InstallMultipleProtocolInterfaces (

+                    &BiosVideoPrivate->Handle,

+                    &gEfiVgaMiniPortProtocolGuid,

+                    &BiosVideoPrivate->VgaMiniPort,

+                    NULL

+                    );

+  }

+

+Done:

+  if (EFI_ERROR (Status)) {

+    //

+    // Free private data structure

+    //

+    BiosVideoDeviceReleaseResource (BiosVideoPrivate);

+  }

+

+  return Status;

+}

+

+/**

+  Deregister an video child handle and free resources

+

+  @param This            Protocol instance pointer.

+  @param Controller      Video controller handle

+  @param Handle          Video child handle

+

+  @return EFI_STATUS

+

+**/

+EFI_STATUS

+BiosVideoChildHandleUninstall (

+  EFI_DRIVER_BINDING_PROTOCOL    *This,

+  EFI_HANDLE                     Controller,

+  EFI_HANDLE                     Handle

+  )

+{

+  EFI_STATUS                   Status;

+  IA32_REGISTER_SET        Regs;

+  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

+  EFI_VGA_MINI_PORT_PROTOCOL   *VgaMiniPort;

+  BIOS_VIDEO_DEV               *BiosVideoPrivate;

+  EFI_PCI_IO_PROTOCOL          *PciIo;

+

+  BiosVideoPrivate = NULL;

+

+  Status = gBS->OpenProtocol (

+                  Handle,

+                  &gEfiGraphicsOutputProtocolGuid,

+                  (VOID **) &GraphicsOutput,

+                  This->DriverBindingHandle,

+                  Handle,

+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                  );

+  if (!EFI_ERROR (Status)) {

+    BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);

+  }

+

+  Status = gBS->OpenProtocol (

+                  Handle,

+                  &gEfiVgaMiniPortProtocolGuid,

+                  (VOID **) &VgaMiniPort,

+                  This->DriverBindingHandle,

+                  Handle,

+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                  );

+  if (!EFI_ERROR (Status)) {

+    BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort);

+  }

+

+  if (BiosVideoPrivate == NULL) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Close PCI I/O protocol that opened by child handle

+  //

+  Status = gBS->CloseProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  This->DriverBindingHandle,

+                  Handle

+                  );

+

+  //

+  // Uninstall protocols on child handle

+  //

+  if (BiosVideoPrivate->ProduceGraphicsOutput) {

+    Status = gBS->UninstallMultipleProtocolInterfaces (

+                    BiosVideoPrivate->Handle,

+                    &gEfiDevicePathProtocolGuid,

+                    BiosVideoPrivate->DevicePath,

+                    &gEfiGraphicsOutputProtocolGuid,

+                    &BiosVideoPrivate->GraphicsOutput,

+                    &gEfiEdidDiscoveredProtocolGuid,

+                    &BiosVideoPrivate->EdidDiscovered,

+                    &gEfiEdidActiveProtocolGuid,

+                    &BiosVideoPrivate->EdidActive,

+                    NULL

+                    );

+  } else {

+    Status = gBS->UninstallMultipleProtocolInterfaces (

+                    BiosVideoPrivate->Handle,

+                    &gEfiVgaMiniPortProtocolGuid,

+                    &BiosVideoPrivate->VgaMiniPort,

+                    NULL

+                    );

+  }

+  if (EFI_ERROR (Status)) {

+    gBS->OpenProtocol (

+           Controller,

+           &gEfiPciIoProtocolGuid,

+           (VOID **) &PciIo,

+           This->DriverBindingHandle,

+           Handle,

+           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+           );

+    return Status;

+  }

+

+  gBS->SetMem (&Regs, sizeof (Regs), 0);

+

+  //

+  // Set the 80x25 Text VGA Mode

+  //

+  Regs.H.AH = 0x00;

+  Regs.H.AL = 0x03;

+  LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+  

+  Regs.H.AH = 0x11;

+  Regs.H.AL = 0x14;

+  Regs.H.BL = 0;

+  LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+  

+  //

+  // Do not disable IO/memory decode since that would prevent legacy ROM from working

+  //

+

+  //

+  // Release all allocated resources

+  //

+  BiosVideoDeviceReleaseResource (BiosVideoPrivate);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Collect the resource from destroyed bios video device.

+

+  @param BiosVideoPrivate   Video child device private data structure

+

+**/

+VOID

+BiosVideoDeviceReleaseResource (

+  BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+{

+  if (BiosVideoPrivate == NULL) {

+    return ;

+  }

+

+  //

+  // Release all the resourses occupied by the BIOS_VIDEO_DEV

+  //

+  

+  //

+  // Free VGA Frame Buffer

+  //

+  if (BiosVideoPrivate->VgaFrameBuffer != NULL) {

+    gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);

+  }

+  //

+  // Free VBE Frame Buffer

+  //

+  if (BiosVideoPrivate->VbeFrameBuffer != NULL) {

+    gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);

+  }

+  //

+  // Free line buffer

+  //

+  if (BiosVideoPrivate->LineBuffer != NULL) {

+    gBS->FreePool (BiosVideoPrivate->LineBuffer);

+  }

+  //

+  // Free mode data

+  //

+  if (BiosVideoPrivate->ModeData != NULL) {

+    gBS->FreePool (BiosVideoPrivate->ModeData);

+  }

+  //

+  // Free memory allocated below 1MB

+  //

+  if (BiosVideoPrivate->PagesBelow1MB != 0) {

+    gBS->FreePages (BiosVideoPrivate->PagesBelow1MB, BiosVideoPrivate->NumberOfPagesBelow1MB);

+  }

+

+  if (BiosVideoPrivate->VbeSaveRestorePages != 0) {

+    gBS->FreePages (BiosVideoPrivate->VbeSaveRestoreBuffer, BiosVideoPrivate->VbeSaveRestorePages);

+  }

+  //

+  // Free graphics output protocol occupied resource

+  //

+  if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {

+    if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {

+        gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);

+    }

+    gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);

+  }

+  //

+  // Free EDID discovered protocol occupied resource

+  //

+  if (BiosVideoPrivate->EdidDiscovered.Edid != NULL) {

+    gBS->FreePool (BiosVideoPrivate->EdidDiscovered.Edid);

+  }

+  //

+  // Free EDID active protocol occupied resource

+  //

+  if (BiosVideoPrivate->EdidActive.Edid != NULL) {

+    gBS->FreePool (BiosVideoPrivate->EdidActive.Edid);

+  }

+

+  if (BiosVideoPrivate->DevicePath!= NULL) {

+    gBS->FreePool (BiosVideoPrivate->DevicePath);

+  }

+

+  gBS->FreePool (BiosVideoPrivate);

+

+  return ;

+}

+

+/**

+

+  Generate a search key for a specified timing data.

+

+

+  @param EdidTiming      - Pointer to EDID timing

+

+  @return The 32 bit unique key for search.

+

+**/

+STATIC

+UINT32

+CalculateEdidKey (

+  VESA_BIOS_EXTENSIONS_EDID_TIMING       *EdidTiming

+  )

+{

+  UINT32 Key;

+

+  //

+  // Be sure no conflicts for all standard timing defined by VESA.

+  //

+  Key = (EdidTiming->HorizontalResolution * 2) + EdidTiming->VerticalResolution;

+  return Key;

+}

+

+/**

+

+  Parse the Established Timing and Standard Timing in EDID data block.

+

+

+  @param EdidBuffer      - Pointer to EDID data block

+  @param ValidEdidTiming - Valid EDID timing information

+

+  @return TRUE              - The EDID data is valid.

+          FALSE             - The EDID data is invalid.

+

+**/

+STATIC

+BOOLEAN

+ParseEdidData (

+  UINT8                                      *EdidBuffer,

+  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming

+  )

+{

+  UINT8  CheckSum;

+  UINT32 Index;

+  UINT32 ValidNumber;

+  UINT32 TimingBits;

+  UINT8  *BufferIndex;

+  UINT16 HorizontalResolution;

+  UINT16 VerticalResolution;

+  UINT8  AspectRatio;

+  UINT8  RefreshRate;

+  VESA_BIOS_EXTENSIONS_EDID_TIMING     TempTiming;

+  VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *EdidDataBlock;

+

+  EdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) EdidBuffer;

+

+  //

+  // Check the checksum of EDID data

+  //

+  CheckSum = 0;

+  for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE; Index ++) {

+    CheckSum = (UINT8)(CheckSum + EdidBuffer[Index]);

+  }

+  if (CheckSum != 0) {

+    return FALSE;

+  }

+

+  ValidNumber = 0;

+  gBS->SetMem (ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING), 0);

+

+  if ((EdidDataBlock->EstablishedTimings[0] != 0) ||

+      (EdidDataBlock->EstablishedTimings[1] != 0) ||

+      (EdidDataBlock->EstablishedTimings[2] != 0)

+      ) {

+    //

+    // Established timing data

+    //

+    TimingBits = EdidDataBlock->EstablishedTimings[0] |

+                 (EdidDataBlock->EstablishedTimings[1] << 8) |

+                 ((EdidDataBlock->EstablishedTimings[2] & 0x80) << 9) ;

+    for (Index = 0; Index < VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER; Index ++) {

+      if (TimingBits & 0x1) {

+        ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&mEstablishedEdidTiming[Index]);

+        ValidNumber ++;

+      }

+      TimingBits = TimingBits >> 1;

+    }

+  } else {

+    //

+    // If no Established timing data, read the standard timing data

+    //

+    BufferIndex = &EdidDataBlock->StandardTimingIdentification[0];

+    for (Index = 0; Index < 8; Index ++) {

+      if ((BufferIndex[0] != 0x1) && (BufferIndex[1] != 0x1)){

+        //

+        // A valid Standard Timing

+        //

+        HorizontalResolution = (UINT8) (BufferIndex[0] * 8 + 248);

+        AspectRatio = (UINT8) (BufferIndex[1] >> 6);

+        switch (AspectRatio) {

+          case 0:

+            VerticalResolution = (UINT8) (HorizontalResolution / 16 * 10);

+            break;

+          case 1:

+            VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);

+            break;

+          case 2:

+            VerticalResolution = (UINT8) (HorizontalResolution / 5 * 4);

+            break;

+          case 3:

+            VerticalResolution = (UINT8) (HorizontalResolution / 16 * 9);

+            break;

+          default:

+            VerticalResolution = (UINT8) (HorizontalResolution / 4 * 3);

+            break;

+        }

+        RefreshRate = (UINT8) ((BufferIndex[1] & 0x1f) + 60);

+        TempTiming.HorizontalResolution = HorizontalResolution;

+        TempTiming.VerticalResolution = VerticalResolution;

+        TempTiming.RefreshRate = RefreshRate;

+        ValidEdidTiming->Key[ValidNumber] = CalculateEdidKey (&TempTiming);

+        ValidNumber ++;

+      }

+      BufferIndex += 2;

+    }

+  }

+

+  ValidEdidTiming->ValidNumber = ValidNumber;

+  return TRUE;

+}

+

+/**

+

+  Search a specified Timing in all the valid EDID timings.

+

+

+  @param ValidEdidTiming - All valid EDID timing information.

+  @param EdidTiming      - The Timing to search for.

+

+  @return TRUE  - Found.

+          FALSE - Not found.

+

+**/

+STATIC

+BOOLEAN

+SearchEdidTiming (

+  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING *ValidEdidTiming,

+  VESA_BIOS_EXTENSIONS_EDID_TIMING       *EdidTiming

+  )

+{

+  UINT32 Index;

+  UINT32 Key;

+

+  Key = CalculateEdidKey (EdidTiming);

+

+  for (Index = 0; Index < ValidEdidTiming->ValidNumber; Index ++) {

+    if (Key == ValidEdidTiming->Key[Index]) {

+      return TRUE;

+    }

+  }

+

+  return FALSE;

+}

+

+#define PCI_DEVICE_ENABLED  (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)

+

+

+/**

+  Judge whether this device is VGA device.

+

+  @param PciIo      Parent PciIo protocol instance pointer

+

+  @retval TRUE  Is vga device

+  @retval FALSE Is no vga device

+**/

+BOOLEAN

+BiosVideoIsVga (

+  IN  EFI_PCI_IO_PROTOCOL       *PciIo

+  )

+{

+  EFI_STATUS    Status;

+  BOOLEAN       VgaCompatible;

+  PCI_TYPE00    Pci;

+

+  VgaCompatible = FALSE;

+

+  //

+  // Read the PCI Configuration Header

+  //

+  Status = PciIo->Pci.Read (

+                        PciIo,

+                        EfiPciIoWidthUint32,

+                        0,

+                        sizeof (Pci) / sizeof (UINT32),

+                        &Pci

+                        );

+  if (EFI_ERROR (Status)) {

+    return VgaCompatible;

+  }

+

+  //

+  // See if this is a VGA compatible controller or not

+  //

+  if ((Pci.Hdr.Command & PCI_DEVICE_ENABLED) == PCI_DEVICE_ENABLED) {

+    if (Pci.Hdr.ClassCode[2] == PCI_CLASS_OLD && Pci.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA) {

+      //

+      // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device

+      //

+      VgaCompatible = TRUE;

+    }

+

+    if (Pci.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY && Pci.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA && Pci.Hdr.ClassCode[0] == 0x00) {

+      //

+      // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller

+      //

+      VgaCompatible = TRUE;

+    }

+  }

+

+  return VgaCompatible;

+}

+

+

+/**

+  Check for VBE device

+

+  @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure

+

+  @retval EFI_SUCCESS VBE device found

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoCheckForVbe (

+  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+{

+  EFI_STATUS                             Status;

+  IA32_REGISTER_SET                  Regs;

+  UINT16                                 *ModeNumberPtr;

+  BOOLEAN                                ModeFound;

+  BOOLEAN                                EdidFound;

+  BIOS_VIDEO_MODE_DATA                   *ModeBuffer;

+  BIOS_VIDEO_MODE_DATA                   *CurrentModeData;

+  UINTN                                  PreferMode;

+  UINTN                                  ModeNumber;

+  VESA_BIOS_EXTENSIONS_EDID_TIMING       Timing;

+  VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming;

+  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE      *GraphicsOutputMode;

+

+  //

+  // Allocate buffer under 1MB for VBE data structures

+  //

+  BiosVideoPrivate->NumberOfPagesBelow1MB = EFI_SIZE_TO_PAGES (

+                                              sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK) +

+                                              sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK) +

+                                              sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK) +

+                                              sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK)

+                                              );

+

+  BiosVideoPrivate->PagesBelow1MB = 0x00100000 - 1;

+

+  Status = gBS->AllocatePages (

+                  AllocateMaxAddress,

+                  EfiBootServicesData,

+                  BiosVideoPrivate->NumberOfPagesBelow1MB,

+                  &BiosVideoPrivate->PagesBelow1MB

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  ZeroMem (&ValidEdidTiming, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING));

+

+  //

+  // Fill in the Graphics Output Protocol

+  //

+  BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;

+  BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;

+  BiosVideoPrivate->GraphicsOutput.Blt     = BiosVideoGraphicsOutputVbeBlt;

+  BiosVideoPrivate->GraphicsOutput.Mode = NULL;

+

+  //

+  // Fill in the VBE related data structures

+  //

+  BiosVideoPrivate->VbeInformationBlock = (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK *) (UINTN) (BiosVideoPrivate->PagesBelow1MB);

+  BiosVideoPrivate->VbeModeInformationBlock = (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeInformationBlock + 1);

+  BiosVideoPrivate->VbeEdidDataBlock = (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK *) (BiosVideoPrivate->VbeModeInformationBlock + 1);

+  BiosVideoPrivate->VbeCrtcInformationBlock = (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *) (BiosVideoPrivate->VbeEdidDataBlock + 1);

+  BiosVideoPrivate->VbeSaveRestorePages   = 0;

+  BiosVideoPrivate->VbeSaveRestoreBuffer  = 0;

+

+  //

+  // Test to see if the Video Adapter is compliant with VBE 3.0

+  //

+  // INT 10 - VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION

+  //

+  //  AX = 4F00h

+  //  ES:DI -> buffer for SuperVGA information (see #00077)

+  // Return: AL = 4Fh if function supported

+  //  AH = status

+  //      00h successful

+  //    ES:DI buffer filled

+  //      01h failed

+  //      ---VBE v2.0---

+  //      02h function not supported by current hardware configuration

+  //      03h function invalid in current video mode

+  // Desc:  determine whether VESA BIOS extensions are present and the capabilities

+  //    supported by the display adapter

+  //

+  gBS->SetMem (&Regs, sizeof (Regs), 0);

+  Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION;

+  gBS->SetMem (BiosVideoPrivate->VbeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK), 0);

+  BiosVideoPrivate->VbeInformationBlock->VESASignature  = VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE;

+  Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeInformationBlock);

+  Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeInformationBlock);

+

+  LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+  Status = EFI_DEVICE_ERROR;

+

+  //

+  // See if the VESA call succeeded

+  //

+  if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {

+    return Status;

+  }

+  //

+  // Check for 'VESA' signature

+  //

+  if (BiosVideoPrivate->VbeInformationBlock->VESASignature != VESA_BIOS_EXTENSIONS_VESA_SIGNATURE) {

+    return Status;

+  }

+  //

+  // Check to see if this is VBE 2.0 or higher

+  //

+  if (BiosVideoPrivate->VbeInformationBlock->VESAVersion < VESA_BIOS_EXTENSIONS_VERSION_2_0) {

+    return Status;

+  }

+

+  //

+  // Read EDID information

+  //

+  // INT 10 - VESA VBE/DC (Display Data Channel) - READ EDID

+  //

+  //    AX = 4F15h

+  //    BL = 01h

+  //    CX = 0000h

+  //    DX = 0000h

+  //    ES:DI -> 128-byte buffer for EDID record (see #00127)

+  // Return: AL = 4Fh if function supported

+  //    AH = status

+  //        00h successful

+  //    ES:DI buffer filled

+  //    01h failed (e.g. non-DDC monitor)

+  //

+  gBS->SetMem (&Regs, sizeof (Regs), 0);

+  Regs.X.AX = VESA_BIOS_EXTENSIONS_EDID;

+  Regs.X.BX = 1;

+  Regs.X.CX = 0;

+  Regs.X.DX = 0;

+  Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);

+  Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeEdidDataBlock);

+

+  LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+  

+  //

+  // See if the VESA call succeeded

+  //

+  EdidFound = FALSE;

+  if (Regs.X.AX == VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {

+    //

+    // Parse EDID data structure to retrieve modes supported by monitor

+    //

+    if (ParseEdidData ((UINT8 *) BiosVideoPrivate->VbeEdidDataBlock, &ValidEdidTiming) == TRUE) {

+      EdidFound = TRUE;

+

+      BiosVideoPrivate->EdidDiscovered.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;

+      Status = gBS->AllocatePool (

+                      EfiBootServicesData,

+                      VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,

+                      (VOID**) &BiosVideoPrivate->EdidDiscovered.Edid

+                      );

+      if (EFI_ERROR (Status)) {

+        goto Done;

+      }

+      gBS->CopyMem (

+             BiosVideoPrivate->EdidDiscovered.Edid,

+             BiosVideoPrivate->VbeEdidDataBlock,

+             VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE

+             );

+

+      BiosVideoPrivate->EdidActive.SizeOfEdid = VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE;

+      Status = gBS->AllocatePool (

+                      EfiBootServicesData,

+                      VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE,

+                      (VOID**)&BiosVideoPrivate->EdidActive.Edid

+                      );

+      if (EFI_ERROR (Status)) {

+        goto Done;

+      }

+      gBS->CopyMem (

+             BiosVideoPrivate->EdidActive.Edid,

+             BiosVideoPrivate->VbeEdidDataBlock,

+             VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE

+             );

+    } else {

+      BiosVideoPrivate->EdidDiscovered.SizeOfEdid = 0;

+      BiosVideoPrivate->EdidDiscovered.Edid = NULL;

+

+      BiosVideoPrivate->EdidActive.SizeOfEdid = 0;

+      BiosVideoPrivate->EdidActive.Edid = NULL;

+    }

+  }

+

+  //

+  // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode

+  //

+  ModeNumberPtr = (UINT16 *)

+    (

+      (((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0xffff0000) >> 12) |

+        ((UINTN) BiosVideoPrivate->VbeInformationBlock->VideoModePtr & 0x0000ffff)

+    );

+

+  PreferMode = 0;

+  ModeNumber = 0;

+

+  for (; *ModeNumberPtr != VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST; ModeNumberPtr++) {

+    //

+    // Make sure this is a mode number defined by the VESA VBE specification.  If it isn'tm then skip this mode number.

+    //

+    if ((*ModeNumberPtr & VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA) == 0) {

+      continue;

+    }

+    //

+    // Get the information about the mode

+    //

+    // INT 10 - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION

+    //

+    //   AX = 4F01h

+    //   CX = SuperVGA video mode (see #04082 for bitfields)

+    //   ES:DI -> 256-byte buffer for mode information (see #00079)

+    // Return: AL = 4Fh if function supported

+    //   AH = status

+    //      00h successful

+    //    ES:DI buffer filled

+    //      01h failed

+    // Desc:  determine the attributes of the specified video mode

+    //

+    gBS->SetMem (&Regs, sizeof (Regs), 0);

+    Regs.X.AX = VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION;

+    Regs.X.CX = *ModeNumberPtr;

+    gBS->SetMem (BiosVideoPrivate->VbeModeInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK), 0);

+    Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);

+    Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeModeInformationBlock);

+

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+    //

+    // See if the call succeeded.  If it didn't, then try the next mode.

+    //

+    if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {

+      continue;

+    }

+    //

+    // See if the mode supports color.  If it doesn't then try the next mode.

+    //

+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR) == 0) {

+      continue;

+    }

+    //

+    // See if the mode supports graphics.  If it doesn't then try the next mode.

+    //

+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS) == 0) {

+      continue;

+    }

+    //

+    // See if the mode supports a linear frame buffer.  If it doesn't then try the next mode.

+    //

+    if ((BiosVideoPrivate->VbeModeInformationBlock->ModeAttributes & VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER) == 0) {

+      continue;

+    }

+    //

+    // See if the mode supports 32 bit color.  If it doesn't then try the next mode.

+    // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the

+    // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel

+    //

+    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel < 24) {

+      continue;

+    }

+

+    if (BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel > 32) {

+      continue;

+    }

+

+    if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel % 8) != 0) {

+      continue;

+    }

+    //

+    // See if the physical base pointer for the linear mode is valid.  If it isn't then try the next mode.

+    //

+    if (BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr == 0) {

+      continue;

+    }

+

+    if (EdidFound && (ValidEdidTiming.ValidNumber > 0)) {

+      //

+      // EDID exist, check whether this mode match with any mode in EDID

+      //

+      Timing.HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;

+      Timing.VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;

+      if (SearchEdidTiming (&ValidEdidTiming, &Timing) == FALSE) {

+        continue;

+      }

+    }

+

+    //

+    // Select a reasonable mode to be set for current display mode

+    //

+    ModeFound = FALSE;

+

+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 1024 &&

+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 768

+        ) {

+      ModeFound = TRUE;

+    }

+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 800 &&

+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 600

+        ) {

+      ModeFound = TRUE;

+      PreferMode = ModeNumber;

+    }

+    if (BiosVideoPrivate->VbeModeInformationBlock->XResolution == 640 &&

+        BiosVideoPrivate->VbeModeInformationBlock->YResolution == 480

+        ) {

+      ModeFound = TRUE;

+    }

+    if ((!EdidFound) && (!ModeFound)) {

+      //

+      // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480

+      //

+      continue;

+    }

+

+    //

+    // Add mode to the list of available modes

+    //

+    ModeNumber ++;

+    Status = gBS->AllocatePool (

+                    EfiBootServicesData,

+                    ModeNumber * sizeof (BIOS_VIDEO_MODE_DATA),

+                    (VOID **) &ModeBuffer

+                    );

+    if (EFI_ERROR (Status)) {

+      goto Done;

+    }

+

+    if (ModeNumber > 1) {

+      gBS->CopyMem (

+            ModeBuffer,

+            BiosVideoPrivate->ModeData,

+            (ModeNumber - 1) * sizeof (BIOS_VIDEO_MODE_DATA)

+            );

+    }

+

+    if (BiosVideoPrivate->ModeData != NULL) {

+      gBS->FreePool (BiosVideoPrivate->ModeData);

+    }

+

+    CurrentModeData = &ModeBuffer[ModeNumber - 1];

+    CurrentModeData->VbeModeNumber = *ModeNumberPtr;

+    if (BiosVideoPrivate->VbeInformationBlock->VESAVersion >= VESA_BIOS_EXTENSIONS_VERSION_3_0) {

+      CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->LinBytesPerScanLine;

+      CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRedFieldPosition;

+      CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRedMaskSize) - 1);

+      CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->LinBlueFieldPosition;

+      CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinBlueMaskSize) - 1);

+      CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->LinGreenFieldPosition;

+      CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinGreenMaskSize) - 1);

+      CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->LinRsvdFieldPosition;

+      CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->LinRsvdMaskSize) - 1);

+    } else {

+      CurrentModeData->BytesPerScanLine = BiosVideoPrivate->VbeModeInformationBlock->BytesPerScanLine;

+      CurrentModeData->Red.Position = BiosVideoPrivate->VbeModeInformationBlock->RedFieldPosition;

+      CurrentModeData->Red.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RedMaskSize) - 1);

+      CurrentModeData->Blue.Position = BiosVideoPrivate->VbeModeInformationBlock->BlueFieldPosition;

+      CurrentModeData->Blue.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->BlueMaskSize) - 1);

+      CurrentModeData->Green.Position = BiosVideoPrivate->VbeModeInformationBlock->GreenFieldPosition;

+      CurrentModeData->Green.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->GreenMaskSize) - 1);

+      CurrentModeData->Reserved.Position = BiosVideoPrivate->VbeModeInformationBlock->RsvdFieldPosition;

+      CurrentModeData->Reserved.Mask = (UINT8) ((1 << BiosVideoPrivate->VbeModeInformationBlock->RsvdMaskSize) - 1);

+    }

+    CurrentModeData->PixelFormat = PixelBitMask;

+    if ((BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel == 32) &&

+        (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {

+      if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {

+        CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;

+      } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {

+        CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;

+      }

+    }

+    CurrentModeData->PixelBitMask.RedMask = ((UINT32) CurrentModeData->Red.Mask) << CurrentModeData->Red.Position;

+    CurrentModeData->PixelBitMask.GreenMask = ((UINT32) CurrentModeData->Green.Mask) << CurrentModeData->Green.Position;

+    CurrentModeData->PixelBitMask.BlueMask = ((UINT32) CurrentModeData->Blue.Mask) << CurrentModeData->Blue.Position;

+    CurrentModeData->PixelBitMask.ReservedMask = ((UINT32) CurrentModeData->Reserved.Mask) << CurrentModeData->Reserved.Position;

+

+    CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN)BiosVideoPrivate->VbeModeInformationBlock->PhysBasePtr;

+    CurrentModeData->FrameBufferSize = BiosVideoPrivate->VbeInformationBlock->TotalMemory * 64 * 1024;

+    CurrentModeData->HorizontalResolution = BiosVideoPrivate->VbeModeInformationBlock->XResolution;

+    CurrentModeData->VerticalResolution = BiosVideoPrivate->VbeModeInformationBlock->YResolution;

+

+    CurrentModeData->BitsPerPixel  = BiosVideoPrivate->VbeModeInformationBlock->BitsPerPixel;

+

+    BiosVideoPrivate->ModeData = ModeBuffer;

+  }

+  //

+  // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT

+  //

+  if (ModeNumber == 0) {

+    Status = EFI_DEVICE_ERROR;

+    goto Done;

+  }

+

+  //

+  // Allocate buffer for Graphics Output Protocol mode information

+  //

+  Status = gBS->AllocatePool (

+                EfiBootServicesData,

+                sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),

+                (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode

+                );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+  GraphicsOutputMode = BiosVideoPrivate->GraphicsOutput.Mode;

+  Status = gBS->AllocatePool (

+                EfiBootServicesData,

+                sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),

+                (VOID **) &GraphicsOutputMode->Info

+                );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  GraphicsOutputMode->MaxMode = (UINT32) ModeNumber;

+  //

+  // Current mode is unknow till now, set it to an invalid mode.

+  //

+  GraphicsOutputMode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;

+

+  //

+  // Find the best mode to initialize

+  //

+  Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, (UINT32) PreferMode);

+  if (EFI_ERROR (Status)) {

+    for (PreferMode = 0; PreferMode < ModeNumber; PreferMode ++) {

+      Status = BiosVideoGraphicsOutputSetMode (

+                &BiosVideoPrivate->GraphicsOutput,

+                (UINT32) PreferMode

+                );

+      if (!EFI_ERROR (Status)) {

+        break;

+      }

+    }

+    if (PreferMode == ModeNumber) {

+      //

+      // None mode is set successfully.

+      //

+      goto Done;

+    }

+  }

+

+Done:

+  //

+  // If there was an error, then free the mode structure

+  //

+  if (EFI_ERROR (Status)) {

+    if (BiosVideoPrivate->ModeData != NULL) {

+      gBS->FreePool (BiosVideoPrivate->ModeData);

+    }

+    if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {

+      if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {

+        gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);

+      }

+      gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);

+    }

+  }

+

+  return Status;

+}

+

+/**

+  Check for VGA device

+

+  @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure

+

+  @retval EFI_SUCCESS  Standard VGA device found

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoCheckForVga (

+  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+{

+  EFI_STATUS            Status;

+  BIOS_VIDEO_MODE_DATA  *ModeBuffer;

+  

+  //

+  // Fill in the Graphics Output Protocol

+  //

+  BiosVideoPrivate->GraphicsOutput.QueryMode = BiosVideoGraphicsOutputQueryMode;

+  BiosVideoPrivate->GraphicsOutput.SetMode = BiosVideoGraphicsOutputSetMode;

+  BiosVideoPrivate->GraphicsOutput.Blt     = BiosVideoGraphicsOutputVgaBlt;

+

+  //

+  // Allocate buffer for Graphics Output Protocol mode information

+  //

+  Status = gBS->AllocatePool (

+                EfiBootServicesData,

+                sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),

+                (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode

+                );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+  Status = gBS->AllocatePool (

+                EfiBootServicesData,

+                sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),

+                (VOID **) &BiosVideoPrivate->GraphicsOutput.Mode->Info

+                );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  //

+  // Add mode to the list of available modes

+  //

+  BiosVideoPrivate->GraphicsOutput.Mode->MaxMode = 1;

+

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  sizeof (BIOS_VIDEO_MODE_DATA),

+                  (VOID **) &ModeBuffer

+                  );

+  if (EFI_ERROR (Status)) {

+    goto Done;

+  }

+

+  ModeBuffer->VbeModeNumber         = 0x0012;

+  ModeBuffer->BytesPerScanLine      = 640;

+  ModeBuffer->LinearFrameBuffer     = (VOID *) (UINTN) (0xa0000);

+  ModeBuffer->FrameBufferSize       = 0;

+  ModeBuffer->HorizontalResolution  = 640;

+  ModeBuffer->VerticalResolution    = 480;

+  ModeBuffer->BitsPerPixel          = 8;  

+  ModeBuffer->PixelFormat           = PixelBltOnly;

+

+  BiosVideoPrivate->ModeData = ModeBuffer;

+

+  //

+  // Test to see if the Video Adapter support the 640x480 16 color mode

+  //

+  BiosVideoPrivate->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;

+  Status = BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate->GraphicsOutput, 0);

+

+Done:

+  //

+  // If there was an error, then free the mode structure

+  //

+  if (EFI_ERROR (Status)) {

+    if (BiosVideoPrivate->ModeData != NULL) {

+      gBS->FreePool (BiosVideoPrivate->ModeData);

+    }

+    if (BiosVideoPrivate->GraphicsOutput.Mode != NULL) {

+      if (BiosVideoPrivate->GraphicsOutput.Mode->Info != NULL) {

+        gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode->Info);

+      }

+      gBS->FreePool (BiosVideoPrivate->GraphicsOutput.Mode);

+    }

+  }

+  return Status;

+}

+//

+// Graphics Output Protocol Member Functions for VESA BIOS Extensions

+//

+/**

+

+  Graphics Output protocol interface to get video mode

+

+

+  @param This            - Protocol instance pointer.

+  @param ModeNumber      - The mode number to return information on.

+  @param SizeOfInfo      - A pointer to the size, in bytes, of the Info buffer.

+  @param Info            - Caller allocated buffer that returns information about ModeNumber.

+

+  @return EFI_SUCCESS           - Mode information returned.

+          EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.

+          EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()

+          EFI_INVALID_PARAMETER - One of the input args was NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputQueryMode (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,

+  IN  UINT32                                ModeNumber,

+  OUT UINTN                                 *SizeOfInfo,

+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info

+  )

+{

+  BIOS_VIDEO_DEV        *BiosVideoPrivate;

+  EFI_STATUS            Status;

+  BIOS_VIDEO_MODE_DATA  *ModeData;

+

+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);

+

+  if (BiosVideoPrivate->HardwareNeedsStarting) {

+    return EFI_NOT_STARTED;

+  }

+

+  if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),

+                  (VOID**) Info

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);

+

+  ModeData = &BiosVideoPrivate->ModeData[ModeNumber];

+  (*Info)->Version = 0;

+  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;

+  (*Info)->VerticalResolution   = ModeData->VerticalResolution;

+  (*Info)->PixelFormat = ModeData->PixelFormat;

+  (*Info)->PixelInformation = ModeData->PixelBitMask;

+

+  (*Info)->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;

+

+  return EFI_SUCCESS;

+}

+

+/**

+

+  Graphics Output protocol interface to set video mode

+

+

+  @param This            - Protocol instance pointer.

+  @param ModeNumber      - The mode number to be set.

+

+  @return EFI_SUCCESS      - Graphics mode was changed.

+          EFI_DEVICE_ERROR - The device had an error and could not complete the request.

+          EFI_UNSUPPORTED  - ModeNumber is not supported by this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputSetMode (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,

+  IN  UINT32                       ModeNumber

+  )

+{

+  EFI_STATUS              Status;

+  BIOS_VIDEO_DEV          *BiosVideoPrivate;

+  IA32_REGISTER_SET   Regs;

+  BIOS_VIDEO_MODE_DATA    *ModeData;

+

+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);

+

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (ModeNumber >= This->Mode->MaxMode) {

+    return EFI_UNSUPPORTED;

+  }

+

+  ModeData = &BiosVideoPrivate->ModeData[ModeNumber];

+

+  if (BiosVideoPrivate->LineBuffer) {

+    gBS->FreePool (BiosVideoPrivate->LineBuffer);

+  }

+

+  if (BiosVideoPrivate->VgaFrameBuffer) {

+    gBS->FreePool (BiosVideoPrivate->VgaFrameBuffer);

+  }

+

+  if (BiosVideoPrivate->VbeFrameBuffer) {

+    gBS->FreePool (BiosVideoPrivate->VbeFrameBuffer);

+  }

+

+  BiosVideoPrivate->LineBuffer = NULL;

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  ModeData->BytesPerScanLine,

+                  (VOID**) &BiosVideoPrivate->LineBuffer

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Clear all registers

+  //

+  gBS->SetMem (&Regs, sizeof (Regs), 0);

+

+  if (ModeData->VbeModeNumber < 0x100) {

+    //

+    // Allocate a working buffer for BLT operations to the VGA frame buffer

+    //

+    BiosVideoPrivate->VgaFrameBuffer = NULL;

+    Status = gBS->AllocatePool (

+                    EfiBootServicesData,

+                    4 * 480 * 80,

+                    (VOID**) &BiosVideoPrivate->VgaFrameBuffer

+                    );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+    //

+    // Set VGA Mode

+    //

+    Regs.X.AX = ModeData->VbeModeNumber;

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+

+  } else {

+    //

+    // Allocate a working buffer for BLT operations to the VBE frame buffer

+    //

+    BiosVideoPrivate->VbeFrameBuffer = NULL;

+    Status = gBS->AllocatePool (

+                    EfiBootServicesData,

+                    ModeData->BytesPerScanLine * ModeData->VerticalResolution,

+                    (VOID**) &BiosVideoPrivate->VbeFrameBuffer

+                    );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+    //

+    // Set VBE mode

+    //

+    Regs.X.AX = VESA_BIOS_EXTENSIONS_SET_MODE;

+    Regs.X.BX = (UINT16) (ModeData->VbeModeNumber | VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER);

+    gBS->SetMem (BiosVideoPrivate->VbeCrtcInformationBlock, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK), 0);

+    Regs.E.ES = EFI_SEGMENT ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);

+    Regs.X.DI = EFI_OFFSET ((UINTN) BiosVideoPrivate->VbeCrtcInformationBlock);

+    

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+    //

+    // Check to see if the call succeeded

+    //

+    if (Regs.X.AX != VESA_BIOS_EXTENSIONS_STATUS_SUCCESS) {

+      return EFI_DEVICE_ERROR;

+    }

+    //

+    // Initialize the state of the VbeFrameBuffer

+    //

+    Status = BiosVideoPrivate->PciIo->Mem.Read (

+                                            BiosVideoPrivate->PciIo,

+                                            EfiPciIoWidthUint32,

+                                            EFI_PCI_IO_PASS_THROUGH_BAR,

+                                            (UINT64) (UINTN) ModeData->LinearFrameBuffer,

+                                            (ModeData->BytesPerScanLine * ModeData->VerticalResolution) >> 2,

+                                            BiosVideoPrivate->VbeFrameBuffer

+                                            );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+  }

+

+  This->Mode->Mode = ModeNumber;

+  This->Mode->Info->Version = 0;

+  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;

+  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;

+  This->Mode->Info->PixelFormat = ModeData->PixelFormat;

+  This->Mode->Info->PixelInformation = ModeData->PixelBitMask;

+  This->Mode->Info->PixelsPerScanLine =  (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;

+  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);

+

+  //

+  // Frame BufferSize remain unchanged

+  //

+  This->Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ModeData->LinearFrameBuffer;

+  This->Mode->FrameBufferSize = ModeData->FrameBufferSize;

+

+  BiosVideoPrivate->HardwareNeedsStarting = FALSE;

+

+  return EFI_SUCCESS;

+}

+

+/**

+

+  Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.

+

+

+  @param PciIo           - The pointer of EFI_PCI_IO_PROTOCOL

+  @param VbeBuffer       - The data to transfer to screen

+  @param MemAddress      - Physical frame buffer base address

+  @param DestinationX    - The X coordinate of the destination for BltOperation

+  @param DestinationY    - The Y coordinate of the destination for BltOperation

+  @param TotalBytes      - The total bytes of copy

+  @param VbePixelWidth   - Bytes per pixel

+  @param BytesPerScanLine - Bytes per scan line

+

+  @return None.

+

+**/

+VOID

+CopyVideoBuffer (

+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,

+  IN  UINT8                 *VbeBuffer,

+  IN  VOID                  *MemAddress,

+  IN  UINTN                 DestinationX,

+  IN  UINTN                 DestinationY,

+  IN  UINTN                 TotalBytes,

+  IN  UINT32                VbePixelWidth,

+  IN  UINTN                 BytesPerScanLine

+  )

+{

+  UINTN                 FrameBufferAddr;

+  UINTN                 CopyBlockNum;

+  UINTN                 RemainingBytes;

+  UINTN                 UnalignedBytes;

+  EFI_STATUS            Status;

+

+  FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;

+

+  //

+  // If TotalBytes is less than 4 bytes, only start byte copy.

+  //

+  if (TotalBytes < 4) {

+    Status = PciIo->Mem.Write (

+                     PciIo,

+                     EfiPciIoWidthUint8,

+                     EFI_PCI_IO_PASS_THROUGH_BAR,

+                     (UINT64) FrameBufferAddr,

+                     TotalBytes,

+                     VbeBuffer

+                     );

+    ASSERT_EFI_ERROR (Status);

+    return;

+  }

+

+  //

+  // If VbeBuffer is not 4-byte aligned, start byte copy.

+  //

+  UnalignedBytes  = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;

+

+  if (UnalignedBytes != 0) {

+    Status = PciIo->Mem.Write (

+                     PciIo,

+                     EfiPciIoWidthUint8,

+                     EFI_PCI_IO_PASS_THROUGH_BAR,

+                     (UINT64) FrameBufferAddr,

+                     UnalignedBytes,

+                     VbeBuffer

+                     );

+    ASSERT_EFI_ERROR (Status);

+    FrameBufferAddr += UnalignedBytes;

+    VbeBuffer       += UnalignedBytes;

+  }

+

+  //

+  // Calculate 4-byte block count and remaining bytes.

+  //

+  CopyBlockNum   = (TotalBytes - UnalignedBytes) >> 2;

+  RemainingBytes = (TotalBytes - UnalignedBytes) &  3;

+

+  //

+  // Copy 4-byte block and remaining bytes to physical frame buffer.

+  //

+  if (CopyBlockNum != 0) {

+    Status = PciIo->Mem.Write (

+                    PciIo,

+                    EfiPciIoWidthUint32,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) FrameBufferAddr,

+                    CopyBlockNum,

+                    VbeBuffer

+                    );

+    ASSERT_EFI_ERROR (Status);

+  }

+

+  if (RemainingBytes != 0) {

+    FrameBufferAddr += (CopyBlockNum << 2);

+    VbeBuffer       += (CopyBlockNum << 2);

+    Status = PciIo->Mem.Write (

+                    PciIo,

+                    EfiPciIoWidthUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) FrameBufferAddr,

+                    RemainingBytes,

+                    VbeBuffer

+                    );

+    ASSERT_EFI_ERROR (Status);

+  }

+}

+

+//

+// BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes

+//

+/**

+

+  Graphics Output protocol instance to block transfer for VBE device

+

+

+  @param This            - Pointer to Graphics Output protocol instance

+  @param BltBuffer       - The data to transfer to screen

+  @param BltOperation    - The operation to perform

+  @param SourceX         - The X coordinate of the source for BltOperation

+  @param SourceY         - The Y coordinate of the source for BltOperation

+  @param DestinationX    - The X coordinate of the destination for BltOperation

+  @param DestinationY    - The Y coordinate of the destination for BltOperation

+  @param Width           - The width of a rectangle in the blt rectangle in pixels

+  @param Height          - The height of a rectangle in the blt rectangle in pixels

+  @param Delta           - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.

+                         If a Delta of 0 is used, the entire BltBuffer will be operated on.

+                         If a subrectangle of the BltBuffer is used, then Delta represents

+                         the number of bytes in a row of the BltBuffer.

+

+  @return EFI_INVALID_PARAMETER - Invalid parameter passed in

+          EFI_SUCCESS - Blt operation success

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputVbeBlt (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,

+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL

+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,

+  IN  UINTN                              SourceX,

+  IN  UINTN                              SourceY,

+  IN  UINTN                              DestinationX,

+  IN  UINTN                              DestinationY,

+  IN  UINTN                              Width,

+  IN  UINTN                              Height,

+  IN  UINTN                              Delta

+  )

+{

+  BIOS_VIDEO_DEV                 *BiosVideoPrivate;

+  BIOS_VIDEO_MODE_DATA           *Mode;

+  EFI_PCI_IO_PROTOCOL            *PciIo;

+  EFI_TPL                        OriginalTPL;

+  UINTN                          DstY;

+  UINTN                          SrcY;

+  UINTN                          DstX;

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *Blt;

+  VOID                           *MemAddress;

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *VbeFrameBuffer;

+  UINTN                          BytesPerScanLine;

+  UINTN                          Index;

+  UINT8                          *VbeBuffer;

+  UINT8                          *VbeBuffer1;

+  UINT8                          *BltUint8;

+  UINT32                         VbePixelWidth;

+  UINT32                         Pixel;

+  UINTN                          TotalBytes;

+

+  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);

+  Mode              = &BiosVideoPrivate->ModeData[This->Mode->Mode];

+  PciIo             = BiosVideoPrivate->PciIo;

+

+  VbeFrameBuffer    = BiosVideoPrivate->VbeFrameBuffer;

+  MemAddress        = Mode->LinearFrameBuffer;

+  BytesPerScanLine  = Mode->BytesPerScanLine;

+  VbePixelWidth     = Mode->BitsPerPixel / 8;

+  BltUint8          = (UINT8 *) BltBuffer;

+  TotalBytes        = Width * VbePixelWidth;

+

+  if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (Width == 0 || Height == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // We need to fill the Virtual Screen buffer with the blt data.

+  // The virtual screen is upside down, as the first row is the bootom row of

+  // the image.

+  //

+  if (BltOperation == EfiBltVideoToBltBuffer) {

+    //

+    // Video to BltBuffer: Source is Video, destination is BltBuffer

+    //

+    if (SourceY + Height > Mode->VerticalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    if (SourceX + Width > Mode->HorizontalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+  } else {

+    //

+    // BltBuffer to Video: Source is BltBuffer, destination is Video

+    //

+    if (DestinationY + Height > Mode->VerticalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    if (DestinationX + Width > Mode->HorizontalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // If Delta is zero, then the entire BltBuffer is being used, so Delta

+  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,

+  // the number of bytes in each row can be computed.

+  //

+  if (Delta == 0) {

+    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

+  }

+  //

+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.

+  // We would not want a timer based event (Cursor, ...) to come in while we are

+  // doing this operation.

+  //

+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);

+

+  switch (BltOperation) {

+  case EfiBltVideoToBltBuffer:

+    for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {

+      Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));

+      //

+      // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL

+      //

+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));

+      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {

+        Pixel         = *(UINT32 *) (VbeBuffer);

+        Blt->Red      = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);

+        Blt->Blue     = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);

+        Blt->Green    = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);

+        Blt->Reserved = 0;

+        Blt++;

+        VbeBuffer += VbePixelWidth;

+      }

+

+    }

+    break;

+

+  case EfiBltVideoToVideo:

+    for (Index = 0; Index < Height; Index++) {

+      if (DestinationY <= SourceY) {

+        SrcY  = SourceY + Index;

+        DstY  = DestinationY + Index;

+      } else {

+        SrcY  = SourceY + Height - Index - 1;

+        DstY  = DestinationY + Height - Index - 1;

+      }

+

+      VbeBuffer   = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);

+      VbeBuffer1  = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);

+

+      gBS->CopyMem (

+            VbeBuffer,

+            VbeBuffer1,

+            TotalBytes

+            );

+

+      //

+      // Update physical frame buffer.

+      //

+      CopyVideoBuffer (

+        PciIo,

+        VbeBuffer,

+        MemAddress,

+        DestinationX,

+        DstY,

+        TotalBytes,

+        VbePixelWidth,

+        BytesPerScanLine

+        );

+    }

+    break;

+

+  case EfiBltVideoFill:

+    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);

+    Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;

+    //

+    // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer

+    //

+    Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |

+      (

+        (Blt->Green & Mode->Green.Mask) <<

+        Mode->Green.Position

+      ) |

+          ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);

+

+    for (Index = 0; Index < Width; Index++) {

+      gBS->CopyMem (

+            VbeBuffer,

+            &Pixel,

+            VbePixelWidth

+            );

+      VbeBuffer += VbePixelWidth;

+    }

+

+    VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);

+    for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {

+      gBS->CopyMem (

+            (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),

+            VbeBuffer,

+            TotalBytes

+            );

+    }

+    for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {

+      //

+      // Update physical frame buffer.

+      //

+      CopyVideoBuffer (

+        PciIo,

+        VbeBuffer,

+        MemAddress,

+        DestinationX,

+        DstY,

+        TotalBytes,

+        VbePixelWidth,

+        BytesPerScanLine

+        );

+    }

+    break;

+

+  case EfiBltBufferToVideo:

+    for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {

+      Blt       = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));

+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));

+      for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {

+        //

+        // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer

+        //

+        Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |

+          ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |

+            ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);

+        gBS->CopyMem (

+              VbeBuffer,

+              &Pixel,

+              VbePixelWidth

+              );

+        Blt++;

+        VbeBuffer += VbePixelWidth;

+      }

+

+      VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));

+

+      //

+      // Update physical frame buffer.

+      //

+      CopyVideoBuffer (

+        PciIo,

+        VbeBuffer,

+        MemAddress,

+        DestinationX,

+        DstY,

+        TotalBytes,

+        VbePixelWidth,

+        BytesPerScanLine

+        );

+    }

+    break;

+  default:

+    break;

+  }

+

+  gBS->RestoreTPL (OriginalTPL);

+

+  return EFI_SUCCESS;

+}

+

+/**

+

+  Write graphics controller registers

+

+

+  @param PciIo           - Pointer to PciIo protocol instance of the controller

+  @param Address         - Register address

+  @param Data            - Data to be written to register

+

+  @return None

+

+**/

+STATIC

+VOID

+WriteGraphicsController (

+  IN  EFI_PCI_IO_PROTOCOL  *PciIo,

+  IN  UINTN                Address,

+  IN  UINTN                Data

+  )

+{

+  Address = Address | (Data << 8);

+  PciIo->Io.Write (

+              PciIo,

+              EfiPciIoWidthUint16,

+              EFI_PCI_IO_PASS_THROUGH_BAR,

+              VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER,

+              1,

+              &Address

+              );

+}

+

+/**

+

+  Read the four bit plane of VGA frame buffer

+

+

+  @param PciIo           - Pointer to PciIo protocol instance of the controller

+  @param HardwareBuffer  - Hardware VGA frame buffer address

+  @param MemoryBuffer    - Memory buffer address

+  @param WidthInBytes    - Number of bytes in a line to read

+  @param Height          - Height of the area to read

+

+  @return None

+

+**/

+VOID

+VgaReadBitPlanes (

+  EFI_PCI_IO_PROTOCOL  *PciIo,

+  UINT8                *HardwareBuffer,

+  UINT8                *MemoryBuffer,

+  UINTN                WidthInBytes,

+  UINTN                Height

+  )

+{

+  UINTN BitPlane;

+  UINTN Rows;

+  UINTN FrameBufferOffset;

+  UINT8 *Source;

+  UINT8 *Destination;

+

+  //

+  // Program the Mode Register Write mode 0, Read mode 0

+  //

+  WriteGraphicsController (

+    PciIo,

+    VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,

+    VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0

+    );

+

+  for (BitPlane = 0, FrameBufferOffset = 0;

+       BitPlane < VGA_NUMBER_OF_BIT_PLANES;

+       BitPlane++, FrameBufferOffset += VGA_BYTES_PER_BIT_PLANE

+      ) {

+    //

+    // Program the Read Map Select Register to select the correct bit plane

+    //

+    WriteGraphicsController (

+      PciIo,

+      VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER,

+      BitPlane

+      );

+

+    Source      = HardwareBuffer;

+    Destination = MemoryBuffer + FrameBufferOffset;

+

+    for (Rows = 0; Rows < Height; Rows++, Source += VGA_BYTES_PER_SCAN_LINE, Destination += VGA_BYTES_PER_SCAN_LINE) {

+      PciIo->Mem.Read (

+                  PciIo,

+                  EfiPciIoWidthUint8,

+                  (UINT8) EFI_PCI_IO_PASS_THROUGH_BAR,

+                  (UINT64)(UINTN) Source,

+                  WidthInBytes,

+                  (VOID *) Destination

+                  );

+    }

+  }

+}

+

+/**

+

+  Internal routine to convert VGA color to Grahpics Output color

+

+

+  @param MemoryBuffer    - Buffer containing VGA color

+  @param X               - The X coordinate of pixel on screen

+  @param Y               - The Y coordinate of pixel on screen

+  @param BltBuffer       - Buffer to contain converted Grahpics Output color

+

+  @return None

+

+**/

+VOID

+VgaConvertToGraphicsOutputColor (

+  UINT8                          *MemoryBuffer,

+  UINTN                          X,

+  UINTN                          Y,

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  *BltBuffer

+  )

+{

+  UINTN Mask;

+  UINTN Bit;

+  UINTN Color;

+

+  MemoryBuffer += ((Y << 6) + (Y << 4) + (X >> 3));

+  Mask = mVgaBitMaskTable[X & 0x07];

+  for (Bit = 0x01, Color = 0; Bit < 0x10; Bit <<= 1, MemoryBuffer += VGA_BYTES_PER_BIT_PLANE) {

+    if (*MemoryBuffer & Mask) {

+      Color |= Bit;

+    }

+  }

+

+  *BltBuffer = mVgaColorToGraphicsOutputColor[Color];

+}

+

+/**

+

+  Internal routine to convert Grahpics Output color to VGA color

+

+

+  @param BltBuffer       - buffer containing Grahpics Output color

+

+  @return Converted VGA color

+

+**/

+UINT8

+VgaConvertColor (

+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL          *BltBuffer

+  )

+{

+  UINT8 Color;

+

+  Color = (UINT8) ((BltBuffer->Blue >> 7) | ((BltBuffer->Green >> 6) & 0x02) | ((BltBuffer->Red >> 5) & 0x04));

+  if ((BltBuffer->Red + BltBuffer->Green + BltBuffer->Blue) > 0x180) {

+    Color |= 0x08;

+  }

+

+  return Color;

+}

+

+/**

+  Grahpics Output protocol instance to block transfer for VGA device

+

+  @param This            Pointer to Grahpics Output protocol instance

+  @param BltBuffer       The data to transfer to screen

+  @param BltOperation    The operation to perform

+  @param SourceX         The X coordinate of the source for BltOperation

+  @param SourceY         The Y coordinate of the source for BltOperation

+  @param DestinationX    The X coordinate of the destination for BltOperation

+  @param DestinationY    The Y coordinate of the destination for BltOperation

+  @param Width           The width of a rectangle in the blt rectangle in pixels

+  @param Height          The height of a rectangle in the blt rectangle in pixels

+  @param Delta           Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.

+                         If a Delta of 0 is used, the entire BltBuffer will be operated on.

+                         If a subrectangle of the BltBuffer is used, then Delta represents

+                         the number of bytes in a row of the BltBuffer.

+

+  @retval EFI_INVALID_PARAMETER Invalid parameter passed in

+  @retval EFI_SUCCESS           Blt operation success

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputVgaBlt (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,

+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL

+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,

+  IN  UINTN                              SourceX,

+  IN  UINTN                              SourceY,

+  IN  UINTN                              DestinationX,

+  IN  UINTN                              DestinationY,

+  IN  UINTN                              Width,

+  IN  UINTN                              Height,

+  IN  UINTN                              Delta

+  )

+{

+  BIOS_VIDEO_DEV      *BiosVideoPrivate;

+  EFI_TPL             OriginalTPL;

+  UINT8               *MemAddress;

+  UINTN               BytesPerScanLine;

+  //UINTN               BytesPerBitPlane;

+  UINTN               Bit;

+  UINTN               Index;

+  UINTN               Index1;

+  UINTN               StartAddress;

+  UINTN               Bytes;

+  UINTN               Offset;

+  UINT8               LeftMask;

+  UINT8               RightMask;

+  UINTN               Address;

+  UINTN               AddressFix;

+  UINT8               *Address1;

+  UINT8               *SourceAddress;

+  UINT8               *DestinationAddress;

+  EFI_PCI_IO_PROTOCOL *PciIo;

+  UINT8               Data;

+  UINT8               PixelColor;

+  UINT8               *VgaFrameBuffer;

+  UINTN               SourceOffset;

+  UINTN               SourceWidth;

+  UINTN               Rows;

+  UINTN               Columns;

+  UINTN               X;

+  UINTN               Y;

+  UINTN               CurrentMode;

+

+  BiosVideoPrivate  = BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);

+

+  CurrentMode = This->Mode->Mode;

+  PciIo             = BiosVideoPrivate->PciIo;

+  MemAddress        = BiosVideoPrivate->ModeData[CurrentMode].LinearFrameBuffer;

+  BytesPerScanLine  = BiosVideoPrivate->ModeData[CurrentMode].BytesPerScanLine >> 3;

+  //BytesPerBitPlane  = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;

+  VgaFrameBuffer    = BiosVideoPrivate->VgaFrameBuffer;

+

+  if (This == NULL || ((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (Width == 0 || Height == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // We need to fill the Virtual Screen buffer with the blt data.

+  // The virtual screen is upside down, as the first row is the bootom row of

+  // the image.

+  //

+  if (BltOperation == EfiBltVideoToBltBuffer) {

+    //

+    // Video to BltBuffer: Source is Video, destination is BltBuffer

+    //

+    if (SourceY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    if (SourceX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+  } else {

+    //

+    // BltBuffer to Video: Source is BltBuffer, destination is Video

+    //

+    if (DestinationY + Height > BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    if (DestinationX + Width > BiosVideoPrivate->ModeData[CurrentMode].HorizontalResolution) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // If Delta is zero, then the entire BltBuffer is being used, so Delta

+  // is the number of bytes in each row of BltBuffer.  Since BltBuffer is Width pixels size,

+  // the number of bytes in each row can be computed.

+  //

+  if (Delta == 0) {

+    Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

+  }

+  //

+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.

+  // We would not want a timer based event (Cursor, ...) to come in while we are

+  // doing this operation.

+  //

+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);

+

+  //

+  // Compute some values we need for VGA

+  //

+  switch (BltOperation) {

+  case EfiBltVideoToBltBuffer:

+

+    SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);

+    SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;

+

+    //

+    // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer

+    //

+    VgaReadBitPlanes (

+      PciIo,

+      MemAddress + SourceOffset,

+      VgaFrameBuffer + SourceOffset,

+      SourceWidth,

+      Height

+      );

+

+    //

+    // Convert VGA Bit Planes to a Graphics Output 32-bit color value

+    //

+    BltBuffer += (DestinationY * (Delta >> 2) + DestinationX);

+    for (Rows = 0, Y = SourceY; Rows < Height; Rows++, Y++, BltBuffer += (Delta >> 2)) {

+      for (Columns = 0, X = SourceX; Columns < Width; Columns++, X++, BltBuffer++) {

+        VgaConvertToGraphicsOutputColor (VgaFrameBuffer, X, Y, BltBuffer);

+      }

+

+      BltBuffer -= Width;

+    }

+

+    break;

+

+  case EfiBltVideoToVideo:

+    //

+    // Check for an aligned Video to Video operation

+    //

+    if ((SourceX & 0x07) == 0x00 && (DestinationX & 0x07) == 0x00 && (Width & 0x07) == 0x00) {

+      //

+      // Program the Mode Register Write mode 1, Read mode 0

+      //

+      WriteGraphicsController (

+        PciIo,

+        VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,

+        VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1

+        );

+

+      SourceAddress       = (UINT8 *) (MemAddress + (SourceY << 6) + (SourceY << 4) + (SourceX >> 3));

+      DestinationAddress  = (UINT8 *) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));

+      Bytes               = Width >> 3;

+      for (Index = 0, Offset = 0; Index < Height; Index++, Offset += BytesPerScanLine) {

+        PciIo->CopyMem (

+                PciIo,

+                EfiPciIoWidthUint8,

+                EFI_PCI_IO_PASS_THROUGH_BAR,

+                (UINT64) ((UINTN)DestinationAddress + Offset),

+                EFI_PCI_IO_PASS_THROUGH_BAR,

+                (UINT64) ((UINTN)SourceAddress + Offset),

+                Bytes

+                );

+      }

+    } else {

+      SourceOffset  = (SourceY << 6) + (SourceY << 4) + (SourceX >> 3);

+      SourceWidth   = ((SourceX + Width - 1) >> 3) - (SourceX >> 3) + 1;

+

+      //

+      // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer

+      //

+      VgaReadBitPlanes (

+        PciIo,

+        MemAddress + SourceOffset,

+        VgaFrameBuffer + SourceOffset,

+        SourceWidth,

+        Height

+        );

+    }

+

+    break;

+

+  case EfiBltVideoFill:

+    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));

+    Bytes         = ((DestinationX + Width - 1) >> 3) - (DestinationX >> 3);

+    LeftMask      = mVgaLeftMaskTable[DestinationX & 0x07];

+    RightMask     = mVgaRightMaskTable[(DestinationX + Width - 1) & 0x07];

+    if (Bytes == 0) {

+      LeftMask = (UINT8) (LeftMask & RightMask);

+      RightMask = 0;

+    }

+

+    if (LeftMask == 0xff) {

+      StartAddress--;

+      Bytes++;

+      LeftMask = 0;

+    }

+

+    if (RightMask == 0xff) {

+      Bytes++;

+      RightMask = 0;

+    }

+

+    PixelColor = VgaConvertColor (BltBuffer);

+

+    //

+    // Program the Mode Register Write mode 2, Read mode 0

+    //

+    WriteGraphicsController (

+      PciIo,

+      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,

+      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2

+      );

+

+    //

+    // Program the Data Rotate/Function Select Register to replace

+    //

+    WriteGraphicsController (

+      PciIo,

+      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,

+      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE

+      );

+

+    if (LeftMask != 0) {

+      //

+      // Program the BitMask register with the Left column mask

+      //

+      WriteGraphicsController (

+        PciIo,

+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,

+        LeftMask

+        );

+

+      for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {

+        //

+        // Read data from the bit planes into the latches

+        //

+        PciIo->Mem.Read (

+                    PciIo,

+                    EfiPciIoWidthUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) Address,

+                    1,

+                    &Data

+                    );

+        //

+        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask

+        //

+        PciIo->Mem.Write (

+                    PciIo,

+                    EfiPciIoWidthUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) Address,

+                    1,

+                    &PixelColor

+                    );

+      }

+    }

+

+    if (Bytes > 1) {

+      //

+      // Program the BitMask register with the middle column mask of 0xff

+      //

+      WriteGraphicsController (

+        PciIo,

+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,

+        0xff

+        );

+

+      for (Index = 0, Address = StartAddress + 1; Index < Height; Index++, Address += BytesPerScanLine) {

+        PciIo->Mem.Write (

+                    PciIo,

+                    EfiPciIoWidthFillUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) Address,

+                    Bytes - 1,

+                    &PixelColor

+                    );

+      }

+    }

+

+    if (RightMask != 0) {

+      //

+      // Program the BitMask register with the Right column mask

+      //

+      WriteGraphicsController (

+        PciIo,

+        VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,

+        RightMask

+        );

+

+      for (Index = 0, Address = StartAddress + Bytes; Index < Height; Index++, Address += BytesPerScanLine) {

+        //

+        // Read data from the bit planes into the latches

+        //

+        PciIo->Mem.Read (

+                    PciIo,

+                    EfiPciIoWidthUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) Address,

+                    1,

+                    &Data

+                    );

+        //

+        // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask

+        //

+        PciIo->Mem.Write (

+                    PciIo,

+                    EfiPciIoWidthUint8,

+                    EFI_PCI_IO_PASS_THROUGH_BAR,

+                    (UINT64) Address,

+                    1,

+                    &PixelColor

+                    );

+      }

+    }

+    break;

+

+  case EfiBltBufferToVideo:

+    StartAddress  = (UINTN) (MemAddress + (DestinationY << 6) + (DestinationY << 4) + (DestinationX >> 3));

+    LeftMask      = mVgaBitMaskTable[DestinationX & 0x07];

+

+    //

+    // Program the Mode Register Write mode 2, Read mode 0

+    //

+    WriteGraphicsController (

+      PciIo,

+      VGA_GRAPHICS_CONTROLLER_MODE_REGISTER,

+      VGA_GRAPHICS_CONTROLLER_READ_MODE_0 | VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2

+      );

+

+    //

+    // Program the Data Rotate/Function Select Register to replace

+    //

+    WriteGraphicsController (

+      PciIo,

+      VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER,

+      VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE

+      );

+

+    for (Index = 0, Address = StartAddress; Index < Height; Index++, Address += BytesPerScanLine) {

+      for (Index1 = 0; Index1 < Width; Index1++) {

+        BiosVideoPrivate->LineBuffer[Index1] = VgaConvertColor (&BltBuffer[(SourceY + Index) * (Delta >> 2) + SourceX + Index1]);

+      }

+      AddressFix = Address;

+

+      for (Bit = 0; Bit < 8; Bit++) {

+        //

+        // Program the BitMask register with the Left column mask

+        //

+        WriteGraphicsController (

+          PciIo,

+          VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER,

+          LeftMask

+          );

+

+        for (Index1 = Bit, Address1 = (UINT8 *) AddressFix; Index1 < Width; Index1 += 8, Address1++) {

+          //

+          // Read data from the bit planes into the latches

+          //

+          PciIo->Mem.Read (

+                      PciIo,

+                      EfiPciIoWidthUint8,

+                      EFI_PCI_IO_PASS_THROUGH_BAR,

+                      (UINT64)(UINTN) Address1,

+                      1,

+                      &Data

+                      );

+

+          PciIo->Mem.Write (

+                      PciIo,

+                      EfiPciIoWidthUint8,

+                      EFI_PCI_IO_PASS_THROUGH_BAR,

+                      (UINT64)(UINTN) Address1,

+                      1,

+                      &BiosVideoPrivate->LineBuffer[Index1]

+                      );

+        }

+

+        LeftMask = (UINT8) (LeftMask >> 1);

+        if (LeftMask == 0) {

+          LeftMask = 0x80;

+          AddressFix++;

+        }

+      }

+    }

+

+    break;

+  default:

+    break;

+  }

+

+  gBS->RestoreTPL (OriginalTPL);

+

+  return EFI_SUCCESS;

+}

+//

+// VGA Mini Port Protocol Functions

+//

+/**

+  VgaMiniPort protocol interface to set mode

+

+  @param This             Pointer to VgaMiniPort protocol instance

+  @param ModeNumber       The index of the mode

+

+  @retval EFI_UNSUPPORTED The requested mode is not supported

+  @retval EFI_SUCCESS     The requested mode is set successfully

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoVgaMiniPortSetMode (

+  IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,

+  IN  UINTN                       ModeNumber

+  )

+{

+  BIOS_VIDEO_DEV        *BiosVideoPrivate;

+  IA32_REGISTER_SET Regs;

+

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Make sure the ModeNumber is a valid value

+  //

+  if (ModeNumber >= This->MaxMode) {

+    return EFI_UNSUPPORTED;

+  }

+  //

+  // Get the device structure for this device

+  //

+  BiosVideoPrivate = BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This);

+  

+  gBS->SetMem (&Regs, sizeof (Regs), 0);

+

+  switch (ModeNumber) {

+  case 0:

+    //

+    // Set the 80x25 Text VGA Mode

+    //

+    Regs.H.AH = 0x00;

+    Regs.H.AL = 0x83;

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+    Regs.H.AH = 0x11;

+    Regs.H.AL = 0x14;

+    Regs.H.BL = 0;

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+    break;

+

+  case 1:

+    //

+    // Set the 80x50 Text VGA Mode

+    //

+    Regs.H.AH = 0x00;

+    Regs.H.AL = 0x83;

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    

+    Regs.H.AH = 0x11;

+    Regs.H.AL = 0x12;

+    Regs.H.BL = 0;

+    LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs);

+    break;

+

+  default:

+    return EFI_UNSUPPORTED;

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.h b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.h
new file mode 100644
index 0000000..37e303e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.h
@@ -0,0 +1,504 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#ifndef _BIOS_GRAPHICS_OUTPUT_H

+#define _BIOS_GRAPHICS_OUTPUT_H

+

+#include <Uefi.h>

+

+//

+// Driver Consumed Protocol Prototypes

+//

+#include <Protocol/DevicePath.h>

+#include <Protocol/PciIo.h>

+#include <Protocol/DriverBinding.h>

+#include <Protocol/ComponentName.h>

+#include <Protocol/ComponentName2.h>

+#include <Protocol/UgaDraw.h>

+#include <Protocol/VgaMiniPort.h>

+#include <Protocol/Legacy8259.h>

+#include <Protocol/EdidActive.h>

+#include <Protocol/EdidDiscovered.h>

+#include <Protocol/DevicePath.h>

+

+#include <Library/UefiLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DevicePathLib.h>

+

+#include <IndustryStandard/Pci.h>

+

+#include "VesaBiosExtensions.h"

+

+//

+// Packed format support: The number of bits reserved for each of the colors and the actual

+// position of RGB in the frame buffer is specified in the VBE Mode information

+//

+typedef struct {

+  UINT8 Position; // Position of the color

+  UINT8 Mask;     // The number of bits expressed as a mask

+} BIOS_VIDEO_COLOR_PLACEMENT;

+

+//

+// BIOS Graphics Output Graphical Mode Data

+//

+typedef struct {

+  UINT16                      VbeModeNumber;

+  UINT16                      BytesPerScanLine;

+  VOID                        *LinearFrameBuffer;

+  UINTN                       FrameBufferSize;

+  UINT32                      HorizontalResolution;

+  UINT32                      VerticalResolution;

+  UINT32                      RefreshRate;

+  UINT32                      BitsPerPixel;

+  BIOS_VIDEO_COLOR_PLACEMENT  Red;

+  BIOS_VIDEO_COLOR_PLACEMENT  Green;

+  BIOS_VIDEO_COLOR_PLACEMENT  Blue;

+  BIOS_VIDEO_COLOR_PLACEMENT  Reserved;

+  EFI_GRAPHICS_PIXEL_FORMAT   PixelFormat;

+  EFI_PIXEL_BITMASK           PixelBitMask;

+} BIOS_VIDEO_MODE_DATA;

+

+//

+// BIOS video child handle private data Structure

+//

+#define BIOS_VIDEO_DEV_SIGNATURE    SIGNATURE_32 ('B', 'V', 'M', 'p')

+

+typedef struct {

+  UINTN                                       Signature;

+  EFI_HANDLE                                  Handle;

+

+  //

+  // Consumed Protocols inherited from parent controller.

+  //

+  EFI_PCI_IO_PROTOCOL                         *PciIo;

+  EFI_LEGACY_8259_PROTOCOL                    *Legacy8259;

+  THUNK_CONTEXT                               *ThunkContext;

+  

+  //

+  // Produced Protocols

+  //

+  EFI_GRAPHICS_OUTPUT_PROTOCOL                GraphicsOutput;

+  EFI_EDID_DISCOVERED_PROTOCOL                EdidDiscovered;

+  EFI_EDID_ACTIVE_PROTOCOL                    EdidActive;

+  EFI_VGA_MINI_PORT_PROTOCOL                  VgaMiniPort;

+

+  //

+  // General fields

+  //

+  BOOLEAN                                     VgaCompatible;

+  BOOLEAN                                     ProduceGraphicsOutput;

+

+  //

+  // Graphics Output Protocol related fields

+  //

+  BOOLEAN                                     HardwareNeedsStarting;

+  BIOS_VIDEO_MODE_DATA                        *ModeData;

+  UINT8                                       *LineBuffer;

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL               *VbeFrameBuffer;

+  UINT8                                       *VgaFrameBuffer;

+

+  //

+  // VESA Bios Extensions related fields

+  //

+  UINTN                                       NumberOfPagesBelow1MB;    // Number of 4KB pages in PagesBelow1MB

+  EFI_PHYSICAL_ADDRESS                        PagesBelow1MB;            // Buffer for all VBE Information Blocks

+  VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK      *VbeInformationBlock;     // 0x200 bytes.  Must be allocated below 1MB

+  VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK *VbeModeInformationBlock; // 0x100 bytes.  Must be allocated below 1MB

+  VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK        *VbeEdidDataBlock;        // 0x80  bytes.  Must be allocated below 1MB

+  VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK *VbeCrtcInformationBlock; // 59 bytes.  Must be allocated below 1MB

+  UINTN                                       VbeSaveRestorePages;      // Number of 4KB pages in VbeSaveRestoreBuffer

+  EFI_PHYSICAL_ADDRESS                        VbeSaveRestoreBuffer;     // Must be allocated below 1MB

+  //

+  // Status code

+  //

+  EFI_DEVICE_PATH_PROTOCOL                    *DevicePath;

+} BIOS_VIDEO_DEV;

+

+#define BIOS_VIDEO_DEV_FROM_PCI_IO_THIS(a)      CR (a, BIOS_VIDEO_DEV, PciIo, BIOS_VIDEO_DEV_SIGNATURE)

+#define BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS(a)      CR (a, BIOS_VIDEO_DEV, GraphicsOutput, BIOS_VIDEO_DEV_SIGNATURE)

+#define BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS(a) CR (a, BIOS_VIDEO_DEV, VgaMiniPort, BIOS_VIDEO_DEV_SIGNATURE)

+

+#define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER  0xffff

+

+#define EFI_SEGMENT(_Adr)     (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000)

+#define EFI_OFFSET(_Adr)      (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff)

+

+//

+// Global Variables

+//

+extern EFI_DRIVER_BINDING_PROTOCOL   gBiosVideoDriverBinding;

+extern EFI_COMPONENT_NAME_PROTOCOL   gBiosVideoComponentName;

+extern EFI_COMPONENT_NAME2_PROTOCOL  gBiosVideoComponentName2;

+

+//

+// Driver Binding Protocol functions

+//

+/**

+  Test to see if Bios Video could be supported on the Controller.

+

+  @param This                  Pointer to driver binding protocol

+  @param Controller            Controller handle to connect

+  @param RemainingDevicePath   A pointer to the remaining portion of a device path

+

+  @retval EFI_SUCCESS         This driver supports this device.

+  @retval other               This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+;

+

+/**

+  Install Graphics Output Protocol onto VGA device handles

+

+  @param This                   Pointer to driver binding protocol

+  @param Controller             Controller handle to connect

+  @param RemainingDevicePath    A pointer to the remaining portion of a device path

+

+  @return EFI_STATUS

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+;

+

+/**

+  Stop this driver on Controller 

+

+  @param  This              Protocol instance pointer.

+  @param  Controller        Handle of device to stop driver on

+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of

+                            children is zero stop the entire bus driver.

+  @param  ChildHandleBuffer List of Child Handles to Stop.

+

+  @retval EFI_SUCCESS       This driver is removed Controller.

+  @retval other             This driver was not removed from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoDriverBindingStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN  EFI_HANDLE                   Controller,

+  IN  UINTN                        NumberOfChildren,

+  IN  EFI_HANDLE                   *ChildHandleBuffer

+  )

+;

+

+//

+// Private worker functions

+//

+/**

+  Check for VBE device

+

+  @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure

+

+  @retval EFI_SUCCESS VBE device found

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoCheckForVbe (

+  IN OUT BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+;

+

+/**

+  Check for VGA device

+

+  @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure

+

+  @retval EFI_SUCCESS  Standard VGA device found

+**/

+

+EFI_STATUS

+EFIAPI

+BiosVideoCheckForVga (

+  BIOS_VIDEO_DEV  *BiosVideoPrivate

+  )

+;

+

+/**

+  Collect the resource from destroyed bios video device.

+

+  @param BiosVideoPrivate   Video child device private data structure

+

+**/

+VOID

+BiosVideoDeviceReleaseResource (

+  BIOS_VIDEO_DEV  *BiosVideoChildPrivate

+  )

+;

+

+//

+// BIOS Graphics Output Protocol functions

+//

+/**

+

+  Graphics Output protocol interface to get video mode

+

+

+  @param This            - Protocol instance pointer.

+  @param ModeNumber      - The mode number to return information on.

+  @param SizeOfInfo      - A pointer to the size, in bytes, of the Info buffer.

+  @param Info            - Caller allocated buffer that returns information about ModeNumber.

+

+  @return EFI_SUCCESS           - Mode information returned.

+          EFI_DEVICE_ERROR      - A hardware error occurred trying to retrieve the video mode.

+          EFI_NOT_STARTED       - Video display is not initialized. Call SetMode ()

+          EFI_INVALID_PARAMETER - One of the input args was NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputQueryMode (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,

+  IN  UINT32                                ModeNumber,

+  OUT UINTN                                 *SizeOfInfo,

+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info

+  )

+;

+

+/**

+

+  Graphics Output protocol interface to set video mode

+

+

+  @param This            - Protocol instance pointer.

+  @param ModeNumber      - The mode number to be set.

+

+  @return EFI_SUCCESS      - Graphics mode was changed.

+          EFI_DEVICE_ERROR - The device had an error and could not complete the request.

+          EFI_UNSUPPORTED  - ModeNumber is not supported by this device.

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputSetMode (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL * This,

+  IN  UINT32                       ModeNumber

+  )

+;

+

+/**

+

+  Graphics Output protocol instance to block transfer for VBE device

+

+

+  @param This            - Pointer to Graphics Output protocol instance

+  @param BltBuffer       - The data to transfer to screen

+  @param BltOperation    - The operation to perform

+  @param SourceX         - The X coordinate of the source for BltOperation

+  @param SourceY         - The Y coordinate of the source for BltOperation

+  @param DestinationX    - The X coordinate of the destination for BltOperation

+  @param DestinationY    - The Y coordinate of the destination for BltOperation

+  @param Width           - The width of a rectangle in the blt rectangle in pixels

+  @param Height          - The height of a rectangle in the blt rectangle in pixels

+  @param Delta           - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.

+                         If a Delta of 0 is used, the entire BltBuffer will be operated on.

+                         If a subrectangle of the BltBuffer is used, then Delta represents

+                         the number of bytes in a row of the BltBuffer.

+

+  @return EFI_INVALID_PARAMETER - Invalid parameter passed in

+          EFI_SUCCESS - Blt operation success

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputVbeBlt (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,

+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL

+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,

+  IN  UINTN                              SourceX,

+  IN  UINTN                              SourceY,

+  IN  UINTN                              DestinationX,

+  IN  UINTN                              DestinationY,

+  IN  UINTN                              Width,

+  IN  UINTN                              Height,

+  IN  UINTN                              Delta

+  )

+;

+

+/**

+  Grahpics Output protocol instance to block transfer for VGA device

+

+  @param This            Pointer to Grahpics Output protocol instance

+  @param BltBuffer       The data to transfer to screen

+  @param BltOperation    The operation to perform

+  @param SourceX         The X coordinate of the source for BltOperation

+  @param SourceY         The Y coordinate of the source for BltOperation

+  @param DestinationX    The X coordinate of the destination for BltOperation

+  @param DestinationY    The Y coordinate of the destination for BltOperation

+  @param Width           The width of a rectangle in the blt rectangle in pixels

+  @param Height          The height of a rectangle in the blt rectangle in pixels

+  @param Delta           Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.

+                         If a Delta of 0 is used, the entire BltBuffer will be operated on.

+                         If a subrectangle of the BltBuffer is used, then Delta represents

+                         the number of bytes in a row of the BltBuffer.

+

+  @retval EFI_INVALID_PARAMETER Invalid parameter passed in

+  @retval EFI_SUCCESS           Blt operation success

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoGraphicsOutputVgaBlt (

+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL       *This,

+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BltBuffer, OPTIONAL

+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION  BltOperation,

+  IN  UINTN                              SourceX,

+  IN  UINTN                              SourceY,

+  IN  UINTN                              DestinationX,

+  IN  UINTN                              DestinationY,

+  IN  UINTN                              Width,

+  IN  UINTN                              Height,

+  IN  UINTN                              Delta

+  )

+;

+

+//

+// BIOS VGA Mini Port Protocol functions

+//

+/**

+  VgaMiniPort protocol interface to set mode

+

+  @param This             Pointer to VgaMiniPort protocol instance

+  @param ModeNumber       The index of the mode

+

+  @retval EFI_UNSUPPORTED The requested mode is not supported

+  @retval EFI_SUCCESS     The requested mode is set successfully

+

+**/

+EFI_STATUS

+EFIAPI

+BiosVideoVgaMiniPortSetMode (

+  IN  EFI_VGA_MINI_PORT_PROTOCOL  *This,

+  IN  UINTN                       ModeNumber

+  )

+;

+

+/**

+  Judge whether this device is VGA device.

+

+  @param PciIo      Parent PciIo protocol instance pointer

+

+  @retval TRUE  Is vga device

+  @retval FALSE Is no vga device

+**/

+BOOLEAN

+BiosVideoIsVga (

+  IN  EFI_PCI_IO_PROTOCOL       *PciIo

+  )

+;

+

+

+//

+// Standard VGA Definitions

+//

+#define VGA_HORIZONTAL_RESOLUTION                         640

+#define VGA_VERTICAL_RESOLUTION                           480

+#define VGA_NUMBER_OF_BIT_PLANES                          4

+#define VGA_PIXELS_PER_BYTE                               8

+#define VGA_BYTES_PER_SCAN_LINE                           (VGA_HORIZONTAL_RESOLUTION / VGA_PIXELS_PER_BYTE)

+#define VGA_BYTES_PER_BIT_PLANE                           (VGA_VERTICAL_RESOLUTION * VGA_BYTES_PER_SCAN_LINE)

+

+#define VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER          0x3ce

+#define VGA_GRAPHICS_CONTROLLER_DATA_REGISTER             0x3cf

+

+#define VGA_GRAPHICS_CONTROLLER_SET_RESET_REGISTER        0x00

+

+#define VGA_GRAPHICS_CONTROLLER_ENABLE_SET_RESET_REGISTER 0x01

+

+#define VGA_GRAPHICS_CONTROLLER_COLOR_COMPARE_REGISTER    0x02

+

+#define VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER      0x03

+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE          0x00

+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_AND              0x08

+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_OR               0x10

+#define VGA_GRAPHICS_CONTROLLER_FUNCTION_XOR              0x18

+

+#define VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER  0x04

+

+#define VGA_GRAPHICS_CONTROLLER_MODE_REGISTER             0x05

+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_0               0x00

+#define VGA_GRAPHICS_CONTROLLER_READ_MODE_1               0x08

+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0              0x00

+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1              0x01

+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2              0x02

+#define VGA_GRAPHICS_CONTROLLER_WRITE_MODE_3              0x03

+

+#define VGA_GRAPHICS_CONTROLLER_MISCELLANEOUS_REGISTER    0x06

+

+#define VGA_GRAPHICS_CONTROLLER_COLOR_DONT_CARE_REGISTER  0x07

+

+#define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER         0x08

+

+/**

+  Initialize legacy environment for BIOS INI caller.

+  

+  @param ThunkContext   the instance pointer of THUNK_CONTEXT

+**/

+VOID

+InitializeBiosIntCaller (

+  THUNK_CONTEXT     *ThunkContext

+  );

+  

+/**

+   Initialize interrupt redirection code and entries, because

+   IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.

+   Or the interrupt will lost when we do thunk.

+   NOTE: We do not reset 8259 vector base, because it will cause pending

+   interrupt lost.

+   

+   @param Legacy8259  Instance pointer for EFI_LEGACY_8259_PROTOCOL.

+   

+**/  

+VOID

+InitializeInterruptRedirection (

+  IN  EFI_LEGACY_8259_PROTOCOL  *Legacy8259

+  );

+  

+/**

+  Thunk to 16-bit real mode and execute a software interrupt with a vector 

+  of BiosInt. Regs will contain the 16-bit register context on entry and 

+  exit.

+  

+  @param  This    Protocol instance pointer.

+  @param  BiosInt Processor interrupt vector to invoke

+  @param  Reg     Register contexted passed into (and returned) from thunk to 16-bit mode

+  

+  @retval TRUE   Thunk completed, and there were no BIOS errors in the target code.

+                 See Regs for status.

+  @retval FALSE  There was a BIOS erro in the target code.  

+**/  

+BOOLEAN

+EFIAPI

+LegacyBiosInt86 (

+  IN  BIOS_VIDEO_DEV                 *BiosDev,

+  IN  UINT8                           BiosInt,

+  IN  IA32_REGISTER_SET           *Regs

+  );    

+  

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.inf b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.inf
new file mode 100644
index 0000000..82243c0
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/BiosVideo.inf
@@ -0,0 +1,50 @@
+## @file

+#  This module provides EFI_GRAPHIC_OUT_PROTOCOL based on functions of video 

+#  on legacy BIOS.

+#  

+#  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = BiosVideo

+  FILE_GUID                      = 29CF55F8-B675-4f5d-8F2F-B87A3ECFD063

+  MODULE_TYPE                    = UEFI_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = BiosVideoDriverEntryPoint

+

+[Packages]

+  MdePkg/MdePkg.dec

+  IntelFrameworkPkg/IntelFrameworkPkg.dec

+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[LibraryClasses]

+  UefiLib

+  DebugLib

+  UefiBootServicesTableLib

+  BaseMemoryLib

+  UefiDriverEntryPoint

+  DevicePathLib

+  

+[Sources]

+  BiosVideo.h

+  BiosVideo.c

+  ComponentName.c

+  VesaBiosExtensions.h

+  LegacyBiosThunk.c

+  

+[Protocols]

+  gEfiPciIoProtocolGuid

+  gEfiVgaMiniPortProtocolGuid

+  gEfiLegacy8259ProtocolGuid

+  gEfiEdidDiscoveredProtocolGuid

+  gEfiEdidActiveProtocolGuid

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/ComponentName.c b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/ComponentName.c
new file mode 100644
index 0000000..364bc3b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/ComponentName.c
@@ -0,0 +1,166 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  ComponentName.c

+

+Abstract:

+

+--*/

+

+#include "BiosVideo.h"

+

+EFI_STATUS

+EFIAPI

+BiosVideoComponentNameGetDriverName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **DriverName

+  );

+  

+EFI_STATUS

+EFIAPI

+BiosVideoComponentNameGetControllerName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,

+  IN  EFI_HANDLE                                      ControllerHandle,

+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,

+  IN  CHAR8                                           *Language,

+  OUT CHAR16                                          **ControllerName

+  );

+    

+//

+// EFI Component Name Protocol

+//

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gBiosVideoComponentName = {

+  BiosVideoComponentNameGetDriverName,

+  BiosVideoComponentNameGetControllerName,

+  "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gBiosVideoComponentName2 = {

+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) BiosVideoComponentNameGetDriverName,

+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) BiosVideoComponentNameGetControllerName,

+  "en"

+};

+

+

+static EFI_UNICODE_STRING_TABLE mBiosVideoDriverNameTable[] = {

+  {

+    "eng;en",

+    L"BIOS[INT10] Video Driver"

+  },

+  {

+    NULL,

+    NULL

+  }

+};

+

+EFI_STATUS

+EFIAPI

+BiosVideoComponentNameGetDriverName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **DriverName

+  )

+/*++

+

+  Routine Description:

+    Retrieves a Unicode string that is the user readable name of the EFI Driver.

+

+  Arguments:

+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+    Language   - A pointer to a three character ISO 639-2 language identifier.

+                 This is the language of the driver name that that the caller 

+                 is requesting, and it must match one of the languages specified

+                 in SupportedLanguages.  The number of languages supported by a 

+                 driver is up to the driver writer.

+    DriverName - A pointer to the Unicode string to return.  This Unicode string

+                 is the name of the driver specified by This in the language 

+                 specified by Language.

+

+  Returns:

+    EFI_SUCCESS           - The Unicode string for the Driver specified by This

+                            and the language specified by Language was returned 

+                            in DriverName.

+    EFI_INVALID_PARAMETER - Language is NULL.

+    EFI_INVALID_PARAMETER - DriverName is NULL.

+    EFI_UNSUPPORTED       - The driver specified by This does not support the 

+                            language specified by Language.

+

+--*/

+{

+  return LookupUnicodeString2 (

+           Language,

+           This->SupportedLanguages,

+           mBiosVideoDriverNameTable,

+           DriverName,

+           (BOOLEAN)(This == &gBiosVideoComponentName)

+           );          

+}

+

+EFI_STATUS

+EFIAPI

+BiosVideoComponentNameGetControllerName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,

+  IN  EFI_HANDLE                                      ControllerHandle,

+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,

+  IN  CHAR8                                           *Language,

+  OUT CHAR16                                          **ControllerName

+  )

+/*++

+

+  Routine Description:

+    Retrieves a Unicode string that is the user readable name of the controller

+    that is being managed by an EFI Driver.

+

+  Arguments:

+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+    ControllerHandle - The handle of a controller that the driver specified by 

+                       This is managing.  This handle specifies the controller 

+                       whose name is to be returned.

+    ChildHandle      - The handle of the child controller to retrieve the name 

+                       of.  This is an optional parameter that may be NULL.  It 

+                       will be NULL for device drivers.  It will also be NULL 

+                       for a bus drivers that wish to retrieve the name of the 

+                       bus controller.  It will not be NULL for a bus driver 

+                       that wishes to retrieve the name of a child controller.

+    Language         - A pointer to a three character ISO 639-2 language 

+                       identifier.  This is the language of the controller name 

+                       that that the caller is requesting, and it must match one

+                       of the languages specified in SupportedLanguages.  The 

+                       number of languages supported by a driver is up to the 

+                       driver writer.

+    ControllerName   - A pointer to the Unicode string to return.  This Unicode

+                       string is the name of the controller specified by 

+                       ControllerHandle and ChildHandle in the language specified

+                       by Language from the point of view of the driver specified

+                       by This. 

+

+  Returns:

+    EFI_SUCCESS           - The Unicode string for the user readable name in the 

+                            language specified by Language for the driver 

+                            specified by This was returned in DriverName.

+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.

+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.

+    EFI_INVALID_PARAMETER - Language is NULL.

+    EFI_INVALID_PARAMETER - ControllerName is NULL.

+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing 

+                            the controller specified by ControllerHandle and 

+                            ChildHandle.

+    EFI_UNSUPPORTED       - The driver specified by This does not support the 

+                            language specified by Language.

+

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/LegacyBiosThunk.c b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/LegacyBiosThunk.c
new file mode 100644
index 0000000..6dc453f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/LegacyBiosThunk.c
@@ -0,0 +1,220 @@
+/** @file

+  Provide legacy thunk interface for accessing Bios Video Rom.

+  

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#include "BiosVideo.h"

+

+#define EFI_CPU_EFLAGS_IF 0x200

+

+/**

+  Initialize legacy environment for BIOS INI caller.

+  

+  @param ThunkContext   the instance pointer of THUNK_CONTEXT

+**/

+VOID

+InitializeBiosIntCaller (

+  THUNK_CONTEXT     *ThunkContext

+  )

+{

+  EFI_STATUS            Status;

+  UINT32                RealModeBufferSize;

+  UINT32                ExtraStackSize;

+  EFI_PHYSICAL_ADDRESS  LegacyRegionBase;

+  UINT32                LegacyRegionSize;

+  //

+  // Get LegacyRegion

+  //

+  AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);

+  LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE;

+  LegacyRegionBase = 0x100000;

+  Status = gBS->AllocatePages (

+                  AllocateMaxAddress,

+                  EfiACPIMemoryNVS,

+                  EFI_SIZE_TO_PAGES(LegacyRegionSize),

+                  &LegacyRegionBase

+                  );

+  ASSERT_EFI_ERROR (Status);

+  

+  ThunkContext->RealModeBuffer     = (VOID*)(UINTN)LegacyRegionBase;

+  ThunkContext->RealModeBufferSize = LegacyRegionSize;

+  ThunkContext->ThunkAttributes    = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15;

+  AsmPrepareThunk16(ThunkContext);

+}

+

+/**

+   Initialize interrupt redirection code and entries, because

+   IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.

+   Or the interrupt will lost when we do thunk.

+   NOTE: We do not reset 8259 vector base, because it will cause pending

+   interrupt lost.

+   

+   @param Legacy8259  Instance pointer for EFI_LEGACY_8259_PROTOCOL.

+   

+**/

+VOID

+InitializeInterruptRedirection (

+  IN  EFI_LEGACY_8259_PROTOCOL  *Legacy8259

+  )

+{

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  LegacyRegionBase;

+  UINTN                 LegacyRegionLength;

+  UINT32                *IdtArray;

+  UINTN                 Index;

+  UINT8                 ProtectedModeBaseVector;

+  UINT32                InterruptRedirectionCode[] = {

+    0x90CF08CD, // INT8; IRET; NOP

+    0x90CF09CD, // INT9; IRET; NOP

+    0x90CF0ACD, // INTA; IRET; NOP

+    0x90CF0BCD, // INTB; IRET; NOP

+    0x90CF0CCD, // INTC; IRET; NOP

+    0x90CF0DCD, // INTD; IRET; NOP

+    0x90CF0ECD, // INTE; IRET; NOP

+    0x90CF0FCD  // INTF; IRET; NOP

+  };

+

+  //

+  // Get LegacyRegion

+  //

+  LegacyRegionLength = sizeof(InterruptRedirectionCode);

+  LegacyRegionBase = 0x100000;

+  Status = gBS->AllocatePages (

+                  AllocateMaxAddress,

+                  EfiACPIMemoryNVS,

+                  EFI_SIZE_TO_PAGES(LegacyRegionLength),

+                  &LegacyRegionBase

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Copy code to legacy region

+  //

+  CopyMem ((VOID *)(UINTN)LegacyRegionBase, InterruptRedirectionCode, sizeof (InterruptRedirectionCode));

+

+  //

+  // Get VectorBase, it should be 0x68

+  //

+  Status = Legacy8259->GetVector (Legacy8259, Efi8259Irq0, &ProtectedModeBaseVector);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Patch IVT 0x68 ~ 0x6f

+  //

+  IdtArray = (UINT32 *) 0;

+  for (Index = 0; Index < 8; Index++) {

+    IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4));

+  }

+

+  return ;

+}

+

+/**

+  Thunk to 16-bit real mode and execute a software interrupt with a vector 

+  of BiosInt. Regs will contain the 16-bit register context on entry and 

+  exit.

+  

+  @param  This    Protocol instance pointer.

+  @param  BiosInt Processor interrupt vector to invoke

+  @param  Reg     Register contexted passed into (and returned) from thunk to 16-bit mode

+  

+  @retval TRUE   Thunk completed, and there were no BIOS errors in the target code.

+                 See Regs for status.

+  @retval FALSE  There was a BIOS erro in the target code.  

+**/

+BOOLEAN

+EFIAPI

+LegacyBiosInt86 (

+  IN  BIOS_VIDEO_DEV                 *BiosDev,

+  IN  UINT8                           BiosInt,

+  IN  IA32_REGISTER_SET              *Regs

+  )

+{

+  UINTN                 Status;

+  IA32_REGISTER_SET     ThunkRegSet;

+  BOOLEAN               Ret;

+  UINT16                *Stack16;

+  BOOLEAN               Enabled;

+  

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

+  ThunkRegSet.E.EFLAGS.Bits.Reserved_0 = 1;

+  ThunkRegSet.E.EFLAGS.Bits.Reserved_1 = 0;

+  ThunkRegSet.E.EFLAGS.Bits.Reserved_2 = 0;

+  ThunkRegSet.E.EFLAGS.Bits.Reserved_3 = 0;

+  ThunkRegSet.E.EFLAGS.Bits.IOPL       = 3;

+  ThunkRegSet.E.EFLAGS.Bits.NT         = 0;

+  ThunkRegSet.E.EFLAGS.Bits.IF         = 1;

+  ThunkRegSet.E.EFLAGS.Bits.TF         = 0;

+  ThunkRegSet.E.EFLAGS.Bits.CF         = 0;

+  

+  ThunkRegSet.E.EDI  = Regs->E.EDI;

+  ThunkRegSet.E.ESI  = Regs->E.ESI;

+  ThunkRegSet.E.EBP  = Regs->E.EBP;

+  ThunkRegSet.E.EBX  = Regs->E.EBX;

+  ThunkRegSet.E.EDX  = Regs->E.EDX;

+  ThunkRegSet.E.ECX  = Regs->E.ECX;

+  ThunkRegSet.E.EAX  = Regs->E.EAX;

+  ThunkRegSet.E.DS   = Regs->E.DS;

+  ThunkRegSet.E.ES   = Regs->E.ES;

+

+  //

+  // The call to Legacy16 is a critical section to EFI

+  //

+  Enabled = SaveAndDisableInterrupts();

+

+  //

+  // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.

+  //

+  Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259LegacyMode, NULL, NULL);

+  ASSERT_EFI_ERROR (Status);

+  

+  Stack16 = (UINT16 *)((UINT8 *) BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16));

+

+  ThunkRegSet.E.SS   = (UINT16) (((UINTN) Stack16 >> 16) << 12);

+  ThunkRegSet.E.ESP  = (UINT16) (UINTN) Stack16;

+

+  ThunkRegSet.E.Eip  = (UINT16)((UINT32 *)NULL)[BiosInt];

+  ThunkRegSet.E.CS   = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);

+  BiosDev->ThunkContext->RealModeState = &ThunkRegSet;

+  AsmThunk16 (BiosDev->ThunkContext);

+  

+  //

+  // Restore protected mode interrupt state

+  //

+  Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259ProtectedMode, NULL, NULL);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // End critical section

+  //

+  SetInterruptState (Enabled);

+

+  Regs->E.EDI      = ThunkRegSet.E.EDI;      

+  Regs->E.ESI      = ThunkRegSet.E.ESI;  

+  Regs->E.EBP      = ThunkRegSet.E.EBP;  

+  Regs->E.EBX      = ThunkRegSet.E.EBX;  

+  Regs->E.EDX      = ThunkRegSet.E.EDX;  

+  Regs->E.ECX      = ThunkRegSet.E.ECX;  

+  Regs->E.EAX      = ThunkRegSet.E.EAX;

+  Regs->E.SS       = ThunkRegSet.E.SS;

+  Regs->E.CS       = ThunkRegSet.E.CS;  

+  Regs->E.DS       = ThunkRegSet.E.DS;  

+  Regs->E.ES       = ThunkRegSet.E.ES;

+

+  CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));

+

+  Ret = (BOOLEAN) (Regs->E.EFLAGS.Bits.CF == 1);

+

+  return Ret;

+}

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h
new file mode 100644
index 0000000..f27cf11
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BiosVideoThunkDxe/VesaBiosExtensions.h
@@ -0,0 +1,457 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  VesaBiosExtensions.h

+

+Abstract:

+

+Revision History

+

+--*/

+

+#ifndef _VESA_BIOS_EXTENSIONS_H

+#define _VESA_BIOS_EXTENSIONS_H

+

+//

+// Turn on byte packing of data structures

+//

+#pragma pack(1)

+//

+// VESA BIOS Extensions status codes

+//

+#define VESA_BIOS_EXTENSIONS_STATUS_SUCCESS 0x004f

+

+//

+// VESA BIOS Extensions Services

+//

+#define VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION  0x4f00

+

+/*++

+

+  Routine Description:

+    Function 00 : Return Controller Information

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f00

+      ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK structure

+    Outputs:

+      AX    = Return Status

+

+--*/

+#define VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION  0x4f01

+

+/*++

+

+  Routine Description:

+    Function 01 : Return Mode Information

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f01

+      CX    = Mode Number

+      ES:DI = Pointer to buffer to place VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK structure

+    Outputs:

+      AX    = Return Status

+

+--*/

+#define VESA_BIOS_EXTENSIONS_SET_MODE 0x4f02

+

+/*++

+

+  Routine Description:

+    Function 02 : Set Mode

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f02

+      BX    = Desired mode to set

+        D0-D8   = Mode Number

+        D9-D10  = Reserved (must be 0)

+        D11     = 0 - Use current default refresh rate

+                = 1 - Use user specfieid CRTC values for refresh rate

+        D12-D13 = Reserved (must be 0)

+        D14     = 0 - Use windowed frame buffer model

+                = 1 - Use linear/flat frame buffer model

+        D15     = 0 - Clear display memory

+                = 1 - Don't clear display memory

+      ES:DI = Pointer to buffer to the VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK structure

+    Outputs:

+      AX    = Return Status

+

+--*/

+#define VESA_BIOS_EXTENSIONS_RETURN_CURRENT_MODE  0x4f03

+

+/*++

+

+  Routine Description:

+    Function 03 : Return Current Mode

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f03

+    Outputs:

+      AX    = Return Status

+      BX    = Current mode

+        D0-D13  = Mode Number

+        D14     = 0 - Windowed frame buffer model

+                = 1 - Linear/flat frame buffer model

+        D15     = 0 - Memory cleared at last mode set

+                = 1 - Memory not cleared at last mode set

+

+--*/

+#define VESA_BIOS_EXTENSIONS_SAVE_RESTORE_STATE 0x4f04

+

+/*++

+

+  Routine Description:

+    Function 04 : Save/Restore State

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f03

+      DL    = 0x00 - Return Save/Restore State buffer size

+            = 0x01 - Save State

+            = 0x02 - Restore State

+      CX    = Requested Status

+        D0  = Save/Restore controller hardware state

+        D1  = Save/Restore BIOS data state

+        D2  = Save/Restore DAC state

+        D3  = Save/Restore Regsiter state

+      ES:BX = Pointer to buffer if DL=1 or DL=2

+    Outputs:

+      AX    = Return Status

+      BX    = Number of 64 byte blocks to hold the state buffer if DL=0

+

+--*/

+#define VESA_BIOS_EXTENSIONS_EDID  0x4f15

+

+/*++

+

+  Routine Description:

+    Function 15 : implement VBE/DDC service

+

+  Arguments:

+    Inputs:

+      AX    = 0x4f15

+      BL    = 0x00 - Report VBE/DDC Capabilities

+      CX    = 0x00 - Controller unit number (00 = primary controller)

+      ES:DI = Null pointer, must be 0:0 in version 1.0

+    Outputs:

+      AX    = Return Status

+      BH    = Approx. time in seconds, rounded up, to transfer one EDID block(128 bytes)

+      BL    = DDC level supported

+        D0  = 0 DDC1 not supported

+            = 1 DDC1 supported

+        D1  = 0 DDC2 not supported

+            = 1 DDC2 supported

+        D2  = 0 Screen not blanked during data transfer

+            = 1 Screen blanked during data transfer

+

+    Inputs:

+      AX    = 0x4f15

+      BL    = 0x01 - Read EDID

+      CX    = 0x00 - Controller unit number (00 = primary controller)

+      DX    = 0x00 - EDID block number

+      ES:DI = Pointer to buffer in which the EDID block is returned

+    Outputs:

+      AX    = Return Status

+--*/

+

+//

+// Timing data from EDID data block

+//

+#define VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE                    128

+#define VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER 17

+

+typedef struct {

+  UINT16  HorizontalResolution;

+  UINT16  VerticalResolution;

+  UINT16  RefreshRate;

+} VESA_BIOS_EXTENSIONS_EDID_TIMING;

+

+typedef struct {

+  UINT32  ValidNumber;

+  UINT32  Key[VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER];

+} VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING;

+

+typedef struct {

+  UINT8   Header[8];                        //EDID header "00 FF FF FF FF FF FF 00"

+  UINT16  ManufactureName;                  //EISA 3-character ID

+  UINT16  ProductCode;                      //Vendor assigned code

+  UINT32  SerialNumber;                     //32-bit serial number

+  UINT8   WeekOfManufacture;                //Week number

+  UINT8   YearOfManufacture;                //Year

+  UINT8   EdidVersion;                      //EDID Structure Version

+  UINT8   EdidRevision;                     //EDID Structure Revision

+  UINT8   VideoInputDefinition;

+  UINT8   MaxHorizontalImageSize;           //cm

+  UINT8   MaxVerticalImageSize;             //cm

+  UINT8   DisplayTransferCharacteristic;

+  UINT8   FeatureSupport;

+  UINT8   RedGreenLowBits;                  //Rx1 Rx0 Ry1 Ry0 Gx1 Gx0 Gy1Gy0

+  UINT8   BlueWhiteLowBits;                 //Bx1 Bx0 By1 By0 Wx1 Wx0 Wy1 Wy0

+  UINT8   RedX;                             //Red-x Bits 9 - 2

+  UINT8   RedY;                             //Red-y Bits 9 - 2

+  UINT8   GreenX;                           //Green-x Bits 9 - 2

+  UINT8   GreenY;                           //Green-y Bits 9 - 2

+  UINT8   BlueX;                            //Blue-x Bits 9 - 2

+  UINT8   BlueY;                            //Blue-y Bits 9 - 2

+  UINT8   WhiteX;                           //White-x Bits 9 - 2

+  UINT8   WhiteY;                           //White-x Bits 9 - 2

+  UINT8   EstablishedTimings[3];

+  UINT8   StandardTimingIdentification[16];

+  UINT8   DetailedTimingDescriptions[72];

+  UINT8   ExtensionFlag;                    //Number of (optional) 128-byte EDID extension blocks to follow

+  UINT8   Checksum;

+} VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK;

+

+//

+// Super VGA Information Block

+//

+typedef struct {

+  UINT32  VESASignature;      // 'VESA' 4 byte signature

+  UINT16  VESAVersion;        // VBE version number

+  UINT32  OEMStringPtr;       // Pointer to OEM string

+  UINT32  Capabilities;       // Capabilities of video card

+  UINT32  VideoModePtr;       // Pointer to an array of 16-bit supported modes values terminated by 0xFFFF

+  UINT16  TotalMemory;        // Number of 64kb memory blocks

+  UINT16  OemSoftwareRev;     // VBE implementation Software revision

+  UINT32  OemVendorNamePtr;   // VbeFarPtr to Vendor Name String

+  UINT32  OemProductNamePtr;  // VbeFarPtr to Product Name String

+  UINT32  OemProductRevPtr;   // VbeFarPtr to Product Revision String

+  UINT8   Reserved[222];      // Reserved for VBE implementation scratch area

+  UINT8   OemData[256];       // Data area for OEM strings.  Pad to 512 byte block size

+} VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK;

+

+//

+// Super VGA Information Block VESASignature values

+//

+#define VESA_BIOS_EXTENSIONS_VESA_SIGNATURE SIGNATURE_32 ('V', 'E', 'S', 'A')

+#define VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE SIGNATURE_32 ('V', 'B', 'E', '2')

+

+//

+// Super VGA Information Block VESAVersion values

+//

+#define VESA_BIOS_EXTENSIONS_VERSION_1_2  0x0102

+#define VESA_BIOS_EXTENSIONS_VERSION_2_0  0x0200

+#define VESA_BIOS_EXTENSIONS_VERSION_3_0  0x0300

+

+//

+// Super VGA Information Block Capabilities field bit defintions

+//

+#define VESA_BIOS_EXTENSIONS_CAPABILITY_8_BIT_DAC 0x01  // 0: DAC width is fixed at 6 bits/color

+// 1: DAC width switchable to 8 bits/color

+//

+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_VGA 0x02  // 0: Controller is VGA compatible

+// 1: Controller is not VGA compatible

+//

+#define VESA_BIOS_EXTENSIONS_CAPABILITY_NOT_NORMAL_RAMDAC 0x04  // 0: Normal RAMDAC operation

+// 1: Use blank bit in function 9 to program RAMDAC

+//

+#define VESA_BIOS_EXTENSIONS_CAPABILITY_STEREOSCOPIC  0x08  // 0: No hardware stereoscopic signal support

+// 1: Hardware stereoscopic signal support

+//

+#define VESA_BIOS_EXTENSIONS_CAPABILITY_VESA_EVC  0x10  // 0: Stero signaling supported via external VESA stereo connector

+// 1: Stero signaling supported via VESA EVC connector

+//

+// Super VGA mode number bite field definitions

+//

+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA 0x0100  // 0: Not a VESA defined VBE mode

+// 1: A VESA defined VBE mode

+//

+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_REFRESH_CONTROL_USER 0x0800  // 0: Use current BIOS default referesh rate

+// 1: Use the user specified CRTC values for refresh rate

+//

+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER  0x4000  // 0: Use a banked/windowed frame buffer

+// 1: Use a linear/flat frame buffer

+//

+#define VESA_BIOS_EXTENSIONS_MODE_NUMBER_PRESERVE_MEMORY  0x8000  // 0: Clear display memory

+// 1: Preseve display memory

+//

+// Super VGA Information Block mode list terminator value

+//

+#define VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST 0xffff

+

+//

+// Window Function

+//

+typedef

+VOID

+(*VESA_BIOS_EXTENSIONS_WINDOW_FUNCTION) (

+  VOID

+  );

+

+//

+// Super VGA Mode Information Block

+//

+typedef struct {

+  //

+  // Manadory fields for all VESA Bios Extensions revisions

+  //

+  UINT16                                ModeAttributes;   // Mode attributes

+  UINT8                                 WinAAttributes;   // Window A attributes

+  UINT8                                 WinBAttributes;   // Window B attributes

+  UINT16                                WinGranularity;   // Window granularity in k

+  UINT16                                WinSize;          // Window size in k

+  UINT16                                WinASegment;      // Window A segment

+  UINT16                                WinBSegment;      // Window B segment

+  UINT32                                WindowFunction;   // Pointer to window function

+  UINT16                                BytesPerScanLine; // Bytes per scanline

+  //

+  // Manadory fields for VESA Bios Extensions 1.2 and above

+  //

+  UINT16                                XResolution;          // Horizontal resolution

+  UINT16                                YResolution;          // Vertical resolution

+  UINT8                                 XCharSize;            // Character cell width

+  UINT8                                 YCharSize;            // Character cell height

+  UINT8                                 NumberOfPlanes;       // Number of memory planes

+  UINT8                                 BitsPerPixel;         // Bits per pixel

+  UINT8                                 NumberOfBanks;        // Number of CGA style banks

+  UINT8                                 MemoryModel;          // Memory model type

+  UINT8                                 BankSize;             // Size of CGA style banks

+  UINT8                                 NumberOfImagePages;   // Number of images pages

+  UINT8                                 Reserved1;            // Reserved

+  UINT8                                 RedMaskSize;          // Size of direct color red mask

+  UINT8                                 RedFieldPosition;     // Bit posn of lsb of red mask

+  UINT8                                 GreenMaskSize;        // Size of direct color green mask

+  UINT8                                 GreenFieldPosition;   // Bit posn of lsb of green mask

+  UINT8                                 BlueMaskSize;         // Size of direct color blue mask

+  UINT8                                 BlueFieldPosition;    // Bit posn of lsb of blue mask

+  UINT8                                 RsvdMaskSize;         // Size of direct color res mask

+  UINT8                                 RsvdFieldPosition;    // Bit posn of lsb of res mask

+  UINT8                                 DirectColorModeInfo;  // Direct color mode attributes

+  //

+  // Manadory fields for VESA Bios Extensions 2.0 and above

+  //

+  UINT32                                PhysBasePtr;  // Physical Address for flat memory frame buffer

+  UINT32                                Reserved2;    // Reserved

+  UINT16                                Reserved3;    // Reserved

+  //

+  // Manadory fields for VESA Bios Extensions 3.0 and above

+  //

+  UINT16                                LinBytesPerScanLine;    // Bytes/scan line for linear modes

+  UINT8                                 BnkNumberOfImagePages;  // Number of images for banked modes

+  UINT8                                 LinNumberOfImagePages;  // Number of images for linear modes

+  UINT8                                 LinRedMaskSize;         // Size of direct color red mask (linear mode)

+  UINT8                                 LinRedFieldPosition;    // Bit posiiton of lsb of red mask (linear modes)

+  UINT8                                 LinGreenMaskSize;       // Size of direct color green mask (linear mode)

+  UINT8                                 LinGreenFieldPosition;  // Bit posiiton of lsb of green mask (linear modes)

+  UINT8                                 LinBlueMaskSize;        // Size of direct color blue mask (linear mode)

+  UINT8                                 LinBlueFieldPosition;   // Bit posiiton of lsb of blue mask (linear modes)

+  UINT8                                 LinRsvdMaskSize;        // Size of direct color reserved mask (linear mode)

+  UINT8                                 LinRsvdFieldPosition;   // Bit posiiton of lsb of reserved mask (linear modes)

+  UINT32                                MaxPixelClock;          // Maximum pixel clock (in Hz) for graphics mode

+  UINT8                                 Pad[190];               // Pad to 256 byte block size

+} VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK;

+

+//

+// Super VGA Mode Information Block ModeAttributes field bit defintions

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_HARDWARE  0x0001  // 0: Mode not supported in handware

+// 1: Mode supported in handware

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_TTY 0x0004  // 0: TTY Output functions not supported by BIOS

+// 1: TTY Output functions supported by BIOS

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR 0x0008  // 0: Monochrome mode

+// 1: Color mode

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS  0x0010  // 0: Text mode

+// 1: Graphics mode

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_VGA 0x0020  // 0: VGA compatible mode

+// 1: Not a VGA compatible mode

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NOT_WINDOWED  0x0040  // 0: VGA compatible windowed memory mode

+// 1: Not a VGA compatible windowed memory mode

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER 0x0080  // 0: No linear fram buffer mode available

+// 1: Linear frame buffer mode available

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DOUBLE_SCAN 0x0100  // 0: No double scan mode available

+// 1: Double scan mode available

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_INTERLACED  0x0200  // 0: No interlaced mode is available

+// 1: Interlaced mode is available

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_NO_TRIPPLE_BUFFER 0x0400  // 0: No hardware triple buffer mode support available

+// 1: Hardware triple buffer mode support available

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_STEREOSCOPIC  0x0800  // 0: No hardware steroscopic display support

+// 1: Hardware steroscopic display support

+//

+#define VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_DUAL_DISPLAY  0x1000  // 0: No dual display start address support

+// 1: Dual display start address support

+//

+// Super VGA Mode Information Block WinAAttribite/WinBAttributes field bit defintions

+//

+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_RELOCATABLE 0x01  // 0: Single non-relocatable window only

+// 1: Relocatable window(s) are supported

+//

+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_READABLE  0x02  // 0: Window is not readable

+// 1: Window is readable

+//

+#define VESA_BIOS_EXTENSIONS_WINX_ATTRIBUTE_WRITABLE  0x04  // 0: Window is not writable

+// 1: Window is writable

+//

+// Super VGA Mode Information Block DirectColorMode field bit defintions

+//

+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_PROG_COLOR_RAMP  0x01  // 0: Color ram is fixed

+// 1: Color ramp is programmable

+//

+#define VESA_BIOS_EXTENSIONS_DIRECT_COLOR_MODE_RSVD_USABLE  0x02  // 0: Bits in Rsvd field are reserved

+// 1: Bits in Rsdv field are usable

+//

+// Super VGA Memory Models

+//

+typedef enum {

+  memPL = 3,  // Planar memory model

+  memPK = 4,  // Packed pixel memory model

+  memRGB= 6,  // Direct color RGB memory model

+  memYUV= 7   // Direct color YUV memory model

+} VESA_BIOS_EXTENSIONS_MEMORY_MODELS;

+

+//

+// Super VGA CRTC Information Block

+//

+typedef struct {

+  UINT16  HorizontalTotal;      // Horizontal total in pixels

+  UINT16  HorizontalSyncStart;  // Horizontal sync start in pixels

+  UINT16  HorizontalSyncEnd;    // Horizontal sync end in pixels

+  UINT16  VericalTotal;         // Vertical total in pixels

+  UINT16  VericalSyncStart;     // Vertical sync start in pixels

+  UINT16  VericalSyncEnd;       // Vertical sync end in pixels

+  UINT8   Flags;                // Flags (Interlaced/DoubleScan/etc).

+  UINT32  PixelClock;           // Pixel clock in units of Hz

+  UINT16  RefreshRate;          // Refresh rate in units of 0.01 Hz

+  UINT8   Reserved[40];         // Pad

+} VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK;

+

+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGS_DOUBLE_SCAN 0x01  // 0: Graphics mode is not souble scanned

+// 1: Graphics mode is double scanned

+//

+#define VESA_BIOS_EXTENSIONS_CRTC_FLAGSINTERLACED 0x02  // 0: Graphics mode is not interlaced

+// 1: Graphics mode is interlaced

+//

+#define VESA_BIOS_EXTENSIONS_CRTC_HORIZONTAL_SYNC_NEGATIVE  0x04  // 0: Horizontal sync polarity is positive(+)

+// 0: Horizontal sync polarity is negative(-)

+//

+#define VESA_BIOS_EXTENSIONS_CRTC_VERITICAL_SYNC_NEGATIVE 0x08  // 0: Verical sync polarity is positive(+)

+// 0: Verical sync polarity is negative(-)

+//

+// Turn off byte packing of data structures

+//

+#pragma pack()

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/BootSector.inf b/uefi/linaro-edk2/DuetPkg/BootSector/BootSector.inf
new file mode 100644
index 0000000..49f69eb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/BootSector.inf
@@ -0,0 +1,79 @@
+## @file

+# 

+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#

+##

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = BootSector

+  FILE_GUID                      = C89D72CE-E21A-4c71-BA79-770EF373D6DA

+  MODULE_TYPE                    = USER_DEFINED

+  VERSION_STRING                 = 1.0

+  CUSTOM_MAKEFILE                = MSFT|Makefile

+  CUSTOM_MAKEFILE                = GCC|GNUmakefile

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[Sources]

+  bootsect.asm | INTEL

+  bootsect.asm | MSFT

+  bootsect.S   | GCC 

+

+  bs16.asm     | INTEL

+  bs16.asm     | MSFT

+  bs16.S       | GCC 

+

+  bs32.asm     | INTEL

+  bs32.asm     | MSFT

+  bs32.S       | GCC

+ 

+  Gpt.asm      | INTEL

+  Gpt.asm      | MSFT

+  Gpt.S        | GCC

+

+  Mbr.asm      | INTEL

+  Mbr.asm      | MSFT

+  Mbr.S        | GCC

+

+  start.asm    | INTEL

+  start.asm    | MSFT

+  start.S      | GCC

+

+  start16.asm  | INTEL

+  start16.asm  | MSFT

+  start16.S    | GCC

+

+  start32.asm  | INTEL

+  start32.asm  | MSFT

+  start32.S    | GCC

+

+  efi32.asm    | INTEL

+  efi32.asm    | MSFT

+  efi32.S      | GCC

+

+  start64.asm  | INTEL

+  start64.asm  | MSFT

+  start64.S    | GCC

+

+  st16_64.asm  | INTEL

+  st16_64.asm  | MSFT

+  st16_64.S    | GCC

+

+  st32_64.asm  | INTEL

+  st32_64.asm  | MSFT

+  st32_64.S    | GCC

+

+  efi64.asm    | INTEL

+  efi64.asm    | MSFT

+  efi64.S      | GCC

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/FILE.LST b/uefi/linaro-edk2/DuetPkg/BootSector/FILE.LST
new file mode 100644
index 0000000..abbe1da
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/FILE.LST
@@ -0,0 +1,39 @@
+## @file

+#

+#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+##

+

+IA32

+====

+FAT12                   FAT16             FAT32

+bootsect.asm            bs16.asm          bs32.asm

+start.asm               start16.asm       start32.asm

+         \                   |                 /

+          \                  |                /

+                         efi32.asm

+

+X64

+===

+FAT12                   FAT16             FAT32

+bootsect.asm            bs16.asm          bs32.asm

+start64.asm             st16_64.asm       st32_64.asm

+         \                   |                 /

+          \                  |                /

+                         efi64.asm

+

+MBR

+===

+Mbr.asm

+

+

+GPT

+===

+Gpt.asm
\ No newline at end of file
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/GNUmakefile b/uefi/linaro-edk2/DuetPkg/BootSector/GNUmakefile
new file mode 100644
index 0000000..da38876
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/GNUmakefile
@@ -0,0 +1,140 @@
+## @file

+#  Just use host GCC to compile boot sector image.

+#

+#  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+#

+##

+

+ASM=gcc

+DLINK=ld

+

+ASSEMBLY_CODE_FILE_LIST = $(MODULE_DIR)/bootsect.S \

+                          $(MODULE_DIR)/bs16.S \

+                          $(MODULE_DIR)/bs32.S \

+                          $(MODULE_DIR)/efi32.S \

+                          $(MODULE_DIR)/efi64.S \

+                          $(MODULE_DIR)/Gpt.S \

+                          $(MODULE_DIR)/Mbr.S \

+                          $(MODULE_DIR)/start.S \

+                          $(MODULE_DIR)/start16.S \

+                          $(MODULE_DIR)/start32.S \

+                          $(MODULE_DIR)/start64.S \

+                          $(MODULE_DIR)/st16_64.S \

+                          $(MODULE_DIR)/st32_64.S

+

+TARGET_FILES = $(OUTPUT_DIR)/bootsect.com \

+               $(OUTPUT_DIR)/bs16.com \

+               $(OUTPUT_DIR)/bs32.com \

+               $(OUTPUT_DIR)/Gpt.com \

+               $(OUTPUT_DIR)/Mbr.com \

+               $(OUTPUT_DIR)/start.com \

+               $(OUTPUT_DIR)/start16.com \

+               $(OUTPUT_DIR)/start32.com \

+               $(OUTPUT_DIR)/efi32.com2 \

+               $(OUTPUT_DIR)/start64.com \

+               $(OUTPUT_DIR)/st16_64.com \

+               $(OUTPUT_DIR)/st32_64.com \

+               $(OUTPUT_DIR)/efi64.com2

+

+.PHONY : all

+all: $(TARGET_FILES)

+

+# bootsect.S

+$(OUTPUT_DIR)/bootsect.o: $(MODULE_DIR)/bootsect.S

+	$(ASM) -c -o $(OUTPUT_DIR)/bootsect.o $(MODULE_DIR)/bootsect.S

+$(OUTPUT_DIR)/bootsect.com: $(OUTPUT_DIR)/bootsect.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/bootsect.com $(OUTPUT_DIR)/bootsect.o -Ttext 0 -Map $(OUTPUT_DIR)/bootsect.map

+

+# bs16.S

+$(OUTPUT_DIR)/bs16.o: $(MODULE_DIR)/bs16.S

+	$(ASM) -c -o $(OUTPUT_DIR)/bs16.o $(MODULE_DIR)/bs16.S

+$(OUTPUT_DIR)/bs16.com: $(OUTPUT_DIR)/bs16.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/bs16.com $(OUTPUT_DIR)/bs16.o -Ttext 0 -Map $(OUTPUT_DIR)/bs16.map

+

+# bs32.S

+$(OUTPUT_DIR)/bs32.o: $(MODULE_DIR)/bs32.S

+	$(ASM) -c -o $(OUTPUT_DIR)/bs32.o $(MODULE_DIR)/bs32.S

+$(OUTPUT_DIR)/bs32.com: $(OUTPUT_DIR)/bs32.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/bs32.com $(OUTPUT_DIR)/bs32.o -Ttext 0 -Map $(OUTPUT_DIR)/bs32.map

+

+# Gpt.S

+$(OUTPUT_DIR)/Gpt.o: $(MODULE_DIR)/Gpt.S

+	$(ASM) -c -o $(OUTPUT_DIR)/Gpt.o $(MODULE_DIR)/Gpt.S

+$(OUTPUT_DIR)/Gpt.com: $(OUTPUT_DIR)/Gpt.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/Gpt.com $(OUTPUT_DIR)/Gpt.o -Ttext 0 -Map $(OUTPUT_DIR)/Gpt.map

+

+# Mbr.S

+$(OUTPUT_DIR)/Mbr.o: $(MODULE_DIR)/Mbr.S

+	$(ASM) -c -o $(OUTPUT_DIR)/Mbr.o $(MODULE_DIR)/Mbr.S

+$(OUTPUT_DIR)/Mbr.com: $(OUTPUT_DIR)/Mbr.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/Mbr.com $(OUTPUT_DIR)/Mbr.o -Ttext 0 -Map $(OUTPUT_DIR)/Mbr.map

+

+# start.S

+$(OUTPUT_DIR)/start.o: $(MODULE_DIR)/start.S

+	$(ASM) -c -o $(OUTPUT_DIR)/start.o $(MODULE_DIR)/start.S

+$(OUTPUT_DIR)/start.com: $(OUTPUT_DIR)/start.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/start.com $(OUTPUT_DIR)/start.o -Ttext 0 -Map $(OUTPUT_DIR)/start.map

+

+# start16.S

+$(OUTPUT_DIR)/start16.o: $(MODULE_DIR)/start16.S

+	$(ASM) -c -o $(OUTPUT_DIR)/start16.o $(MODULE_DIR)/start16.S

+$(OUTPUT_DIR)/start16.com: $(OUTPUT_DIR)/start16.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/start16.com $(OUTPUT_DIR)/start16.o -Ttext 0 -Map $(OUTPUT_DIR)/start16.map

+

+# start32.S

+$(OUTPUT_DIR)/start32.o: $(MODULE_DIR)/start32.S

+	$(ASM) -c -o $(OUTPUT_DIR)/start32.o $(MODULE_DIR)/start32.S

+$(OUTPUT_DIR)/start32.com: $(OUTPUT_DIR)/start32.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/start32.com $(OUTPUT_DIR)/start32.o -Ttext 0 -Map $(OUTPUT_DIR)/start32.map

+

+# start64.S

+$(OUTPUT_DIR)/start64.o: $(MODULE_DIR)/start64.S

+	$(ASM) -c -o $(OUTPUT_DIR)/start64.o $(MODULE_DIR)/start64.S

+$(OUTPUT_DIR)/start64.com: $(OUTPUT_DIR)/start64.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/start64.com $(OUTPUT_DIR)/start64.o -Ttext 0 -Map $(OUTPUT_DIR)/start64.map

+

+# start16_64.S

+$(OUTPUT_DIR)/st16_64.o: $(MODULE_DIR)/st16_64.S

+	$(ASM) -c -o $(OUTPUT_DIR)/st16_64.o $(MODULE_DIR)/st16_64.S

+$(OUTPUT_DIR)/st16_64.com: $(OUTPUT_DIR)/st16_64.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/st16_64.com $(OUTPUT_DIR)/st16_64.o -Ttext 0 -Map $(OUTPUT_DIR)/st16_64.map

+

+# start32_64.S

+$(OUTPUT_DIR)/st32_64.o: $(MODULE_DIR)/st32_64.S

+	$(ASM) -c -o $(OUTPUT_DIR)/st32_64.o $(MODULE_DIR)/st32_64.S

+$(OUTPUT_DIR)/st32_64.com: $(OUTPUT_DIR)/st32_64.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/st32_64.com $(OUTPUT_DIR)/st32_64.o -Ttext 0 -Map $(OUTPUT_DIR)/st32_64.map

+

+# efi32.S

+$(OUTPUT_DIR)/efi32.o: $(MODULE_DIR)/efi32.S

+	$(ASM) -c -o $(OUTPUT_DIR)/efi32.o $(MODULE_DIR)/efi32.S

+$(OUTPUT_DIR)/efi32.com: $(OUTPUT_DIR)/efi32.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/efi32.com $(OUTPUT_DIR)/efi32.o -Ttext 0 -Map $(OUTPUT_DIR)/efi32.map

+$(OUTPUT_DIR)/efi32.com2: $(OUTPUT_DIR)/efi32.com

+	Split -f $(OUTPUT_DIR)/efi32.com -p $(OUTPUT_DIR) -o efi32.com1 -p $(OUTPUT_DIR) -t efi32.com2 -s 135168

+

+# efi64.S

+$(OUTPUT_DIR)/efi64.o: $(MODULE_DIR)/efi64.S

+	$(ASM) -c -o $(OUTPUT_DIR)/efi64.o $(MODULE_DIR)/efi64.S

+$(OUTPUT_DIR)/efi64.com: $(OUTPUT_DIR)/efi64.o

+	$(DLINK) --oformat binary -o $(OUTPUT_DIR)/efi64.com $(OUTPUT_DIR)/efi64.o -Ttext 0 -Map $(OUTPUT_DIR)/efi64.map

+$(OUTPUT_DIR)/efi64.com2: $(OUTPUT_DIR)/efi64.com

+	Split -f $(OUTPUT_DIR)/efi64.com -p $(OUTPUT_DIR) -o efi64.com1 -p $(OUTPUT_DIR) -t efi64.com2 -s 135168

+

+clean:

+ifneq ($(OUTPUT_DIR), )

+	rm -r $(OUTPUT_DIR)

+endif

+ifneq ($(DEBUG_DIR), )

+	rm -r $(DEBUG_DIR)

+endif

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.S b/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.S
new file mode 100644
index 0000000..821ca84
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.S
@@ -0,0 +1,297 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    gpt.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+    #.MODEL small

+#   .dosseg

+    .stack: 

+    .486p: 

+    .code16 

+

+.equ                      BLOCK_SIZE,  0x0200

+.equ                      BLOCK_MASK,  0x01ff

+.equ                      BLOCK_SHIFT, 9

+

+# ****************************************************************************

+# Code loaded by BIOS at 0x0000:0x7C00

+# ****************************************************************************

+

+        .org 0x00

+Start: 

+

+# ****************************************************************************

+# Start Print

+# ****************************************************************************

+

+    movw $0xb800, %ax

+    movw %ax, %es

+    movw $0x7c0, %ax

+    movw %ax, %ds

+    leaw %cs:StartString, %si

+    movw $10, %cx

+    movw $160, %di

+    rep

+    movsw

+

+# ****************************************************************************

+# Print over

+# ****************************************************************************

+

+# ****************************************************************************

+# Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600

+# ****************************************************************************

+        xorw  %ax, %ax                  # AX = 0x0000  

+        movw  $0x7c00, %bx              # BX = 0x7C00

+        movw  $0x600, %bp               # BP = 0x0600

+        movw  RelocatedStart, %si       # SI = Offset(RelocatedStart)

+        movw  $0x200, %cx               # CX = 0x0200

+        subw  %si, %cx                  # CS = 0x0200 - Offset(RelocatedStart)

+        leaw  (%bp,%si,), %di           # DI = 0x0600 + Offset(RelocatedStart)

+        leaw  (%bx,%si,), %si           # BX = 0x7C00 + Offset(RelocatedStart)

+        movw  %ax, %ss                  # SS = 0x0000

+        movw  %bx, %sp                  # SP = 0x7C00

+        movw  %ax, %es                  # ES = 0x0000

+        movw  %ax, %ds                  # DS = 0x0000

+        pushw %ax                       # PUSH 0x0000

+        pushw %di                       # PUSH 0x0600 + Offset(RelocatedStart)

+        cld                             # Clear the direction flag

+        rep

+        movsb                           # Copy 0x0200 bytes from 0x7C00 to 0x0600

+        retl                            # JMP 0x0000:0x0600 + Offset(RelocatedStart)

+

+# ****************************************************************************

+# Code relocated to 0x0000:0x0600

+# ****************************************************************************

+

+RelocatedStart: 

+# ****************************************************************************

+# Get Driver Parameters to 0x0000:0x7BFC

+# ****************************************************************************

+        xorw  %ax, %ax      # ax = 0

+        movw  %ax, %ss      # ss = 0

+        addw  $0x1000, %ax

+        movw  %ax, %ds

+

+        movw  $0x7c00, %sp  # sp = 0x7c00

+        movw  %sp, %bp      # bp = 0x7c00

+

+        movb  $8, %ah                             # ah = 8 - Get Drive Parameters Function

+        movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL

+        int   $0x13                               # Get Drive Parameters

+        xorw  %ax, %ax                # ax = 0

+        movb  %dh, %al                # al = dh

+        incb  %al                     # MaxHead = al + 1

+        pushw %ax                     # 0000:7bfe = MaxHead

+        movb  %cl, %al                # al = cl

+        andb  $0x3f, %al              # MaxSector = al & 0x3f

+        pushw %ax                     # 0000:7bfc = MaxSector

+

+# ****************************************************************************

+# Read GPT Header from hard disk to 0x0000:0x0800

+# ****************************************************************************

+        xorw    %ax, %ax

+        movw    %ax, %es                          # Read to 0x0000:0x0800

+        movw    $0x800, %di                       # Read to 0x0000:0x0800

+        movl    $1, %eax                          # Read LBA #1

+        movl    $0, %edx                          # Read LBA #1

+        movw    $1, %bx                           # Read 1 Block

+        pushw   %es

+        call    ReadBlocks

+        popw    %es

+

+# ****************************************************************************

+# Read Target GPT Entry from hard disk to 0x0000:0x0A00

+# ****************************************************************************

+        cmpl  $0x20494645, %es:(%di)              # Check for "EFI "

+        jne   BadGpt

+        cmpl  $0x54524150, %es:4(%di)             # Check for "PART"

+        jne   BadGpt

+        cmpl  $0x00010000, %es:8(%di)             # Check Revision - 0x10000

+        jne   BadGpt

+

+        movl  %es:84(%di), %eax                   # EAX = SizeOfPartitionEntry

+        mulb  GptPartitionIndicator(%bp)          # EAX = SizeOfPartitionEntry * GptPartitionIndicator

+        movl  %eax, %edx                          # EDX = SizeOfPartitionEntry * GptPartitionIndicator

+        shrl  $BLOCK_SHIFT, %eax                  # EAX = (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE

+        andl  $BLOCK_MASK, %edx                   # EDX = Targer PartitionEntryLBA Offset

+                                                  #     = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE

+        pushl %edx

+        movl  %es:72(%di), %ecx                   # ECX = PartitionEntryLBA (Low)

+        movl  %es:76(%di), %ebx                   # EBX = PartitionEntryLBA (High)

+        addl  %ecx, %eax                          # EAX = Target PartitionEntryLBA (Low)

+                                                  #     = (PartitionEntryLBA + 

+                                                  #        (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE)

+        adcl  %ebx, %edx                          # EDX = Target PartitionEntryLBA (High)

+

+        movw  $0xA00, %di                         # Read to 0x0000:0x0A00

+        movw  $1, %bx                             # Read 1 Block

+        pushw %es

+        call  ReadBlocks

+        popw  %es

+

+# ****************************************************************************

+# Read Target DBR from hard disk to 0x0000:0x7C00

+# ****************************************************************************

+        popl  %edx                                # EDX = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE

+        addw  %dx, %di                            # DI = Targer PartitionEntryLBA Offset

+        cmpl  $0xC12A7328, %es:(%di)              # Check for EFI System Partition "C12A7328-F81F-11d2-BA4B-00A0C93EC93B"

+        jne   BadGpt

+        cmpl  $0x11d2F81F, %es:4(%di)             # 

+        jne   BadGpt

+        cmpl  $0xA0004BBA, %es:8(%di)             # 

+        jne   BadGpt

+        cmpl  $0x3BC93EC9, %es:0xc(%di)           # 

+        jne   BadGpt

+

+        movl  %es:32(%di), %eax                   # EAX = StartingLBA (Low)

+        movl  %es:36(%di), %edx                   # EDX = StartingLBA (High)

+        movw  $0x7C00, %di                        # Read to 0x0000:0x7C00

+        movw  $1, %bx                             # Read 1 Block

+        call  ReadBlocks

+

+# ****************************************************************************

+# Transfer control to BootSector - Jump to 0x0000:0x7C00

+# ****************************************************************************

+        xorw  %ax, %ax

+        pushw %ax                       # PUSH 0x0000

+        movw  $0x7c00, %di

+        pushw %di                       # PUSH 0x7C00

+        retl                            # JMP 0x0000:0x7C00

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# EDX:EAX = Start LBA

+# BX      = Number of Blocks to Read (must < 127)

+# ES:DI   = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# si = DiskAddressPacket

+

+ReadBlocks: 

+        pushal

+        pushw %ds

+        xorw  %cx, %cx

+        movw  %cx, %ds

+        movw  $0x600, %bp                       # bp = 0x600

+        leaw  AddressPacket(%bp), %si

+        movb  %bl, %ds:2(%si)                   #    02 = Number Of Block transfered

+        movw  %di, %ds:4(%si)                   #    04 = Transfer Buffer Offset

+        movw  %es, %ds:6(%si)                   #    06 = Transfer Buffer Segment

+        movl  %eax, %ds:8(%si)                  #    08 = Starting LBA (Low)

+        movl  %edx, %ds:0xc(%si)                #    0C = Starting LBA (High)

+        movb  $0x42, %ah                        # ah = Function 42

+        movb  PhysicalDrive(%bp), %dl           # dl = Drive Number

+        int   $0x13

+        jc    BadGpt

+        popw  %ds

+        popal

+        ret

+

+# ****************************************************************************

+# Address Packet used by ReadBlocks

+# ****************************************************************************

+AddressPacket: 

+        .byte 0x10                      # Size of address packet

+        .byte 0x0                       # Reserved.  Must be 0

+        .byte 0x1                       # Read blocks at a time (To be fixed each times)

+        .byte 0x0                       # Reserved.  Must be 0

+        .word 0x000                     # Destination Address offset (To be fixed each times)

+        .word 0x000                     # Destination Address segment (To be fixed each times)

+AddressPacketLba: 

+        .long 0x0,0x0                   # Start LBA (To be fixed each times)

+AddressPacketEnd: 

+

+# ****************************************************************************

+# ERROR Condition:

+# ****************************************************************************

+

+BadGpt: 

+    movw $0xb800, %ax

+    movw %ax, %es

+    movw $0x60, %ax

+    movw %ax, %ds

+    leaw %cs:ErrorString, %si

+    movw $10, %cx

+    movw $320, %di

+    rep

+    movsw

+Halt: 

+    jmp   Halt

+

+StartString: 

+    .byte 'G', 0x0c, 'P', 0x0c, 'T', 0x0c, ' ', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c

+ErrorString: 

+    .byte 'G', 0x0c, 'P', 0x0c, 'T', 0x0c, ' ', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c

+

+# ****************************************************************************

+# PhysicalDrive - Used to indicate which disk to be boot

+#                 Can be patched by tool

+# ****************************************************************************

+    # .org   0x01B6 # Just for passing build.

+PhysicalDrive:        .byte 0x80

+

+# ****************************************************************************

+# GptPartitionIndicator - Used to indicate which GPT partition to be boot

+#                         Can be patched by tool

+# ****************************************************************************

+   # .org   0x01B7  # Just for passing build.

+GptPartitionIndicator: .byte 0

+

+# ****************************************************************************

+# Unique MBR signature

+# ****************************************************************************

+   # .org   0x01B8  # Just for passing build.

+    .ascii "DUET"

+

+# ****************************************************************************

+# Unknown

+# ****************************************************************************

+    # .org   0x01BC  # Just for passing build.

+    .word 0

+

+# ****************************************************************************

+# PMBR Entry - Can be patched by tool

+# ****************************************************************************

+    # .org   0x01BE  # Just for passing build.

+    .byte 0       # Boot Indicator

+    .byte 0xff    # Start Header

+    .byte 0xff    # Start Sector

+    .byte 0xff    # Start Track

+    .byte 0xee    # OS Type

+    .byte 0xff    # End Header

+    .byte 0xff    # End Sector

+    .byte 0xff    # End Track

+    .long 1       # Starting LBA

+    .long 0xFFFFFFFF # End LBA

+

+    # .org   0x01CE  # Just for passing build.

+    .long  0,0,0,0

+    # .org   0x01DE  # Just for passing build.

+    .long  0,0,0,0

+    # .org   0x01EE  # Just for passing build.

+    .long 0,0,0,0

+

+# ****************************************************************************

+# Sector Signature

+# ****************************************************************************

+

+  # .org      0x01FE  # Just for passing build.

+SectorSignature: 

+  .word     0xaa55      # Boot Sector Signature

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.asm b/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.asm
new file mode 100644
index 0000000..e940753
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/Gpt.asm
@@ -0,0 +1,294 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    gpt.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+    .model  small

+;   .dosseg

+    .stack

+    .486p

+    .code

+

+BLOCK_SIZE                EQU     0200h

+BLOCK_MASK                EQU     01ffh

+BLOCK_SHIFT               EQU     9

+

+; ****************************************************************************

+; Code loaded by BIOS at 0x0000:0x7C00

+; ****************************************************************************

+

+        org 0h

+Start:

+

+; ****************************************************************************

+; Start Print

+; ****************************************************************************

+

+    mov  ax,0b800h

+    mov  es,ax

+    mov  ax, 07c0h

+    mov  ds, ax

+    lea  si, cs:[StartString]

+    mov  cx, 10

+    mov  di, 160

+    rep  movsw 

+

+; ****************************************************************************

+; Print over

+; ****************************************************************************

+

+; ****************************************************************************

+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600

+; ****************************************************************************

+        xor   ax, ax                    ; AX = 0x0000  

+        mov   bx, 07c00h                ; BX = 0x7C00

+        mov   bp, 0600h                 ; BP = 0x0600

+        mov   si, OFFSET RelocatedStart ; SI = Offset(RelocatedStart)

+        mov   cx, 0200h                 ; CX = 0x0200

+        sub   cx, si                    ; CS = 0x0200 - Offset(RelocatedStart)

+        lea   di, [bp+si]               ; DI = 0x0600 + Offset(RelocatedStart)

+        lea   si, [bx+si]               ; BX = 0x7C00 + Offset(RelocatedStart)

+        mov   ss, ax                    ; SS = 0x0000

+        mov   sp, bx                    ; SP = 0x7C00

+        mov   es,ax                     ; ES = 0x0000

+        mov   ds,ax                     ; DS = 0x0000

+        push  ax                        ; PUSH 0x0000

+        push  di                        ; PUSH 0x0600 + Offset(RelocatedStart)

+        cld                             ; Clear the direction flag

+        rep   movsb                     ; Copy 0x0200 bytes from 0x7C00 to 0x0600

+        retf                            ; JMP 0x0000:0x0600 + Offset(RelocatedStart)

+

+; ****************************************************************************

+; Code relocated to 0x0000:0x0600

+; ****************************************************************************

+

+RelocatedStart:

+; ****************************************************************************

+; Get Driver Parameters to 0x0000:0x7BFC

+; ****************************************************************************

+        xor   ax,ax         ; ax = 0

+        mov   ss,ax         ; ss = 0

+        add   ax,1000h

+        mov   ds,ax

+

+        mov   sp,07c00h     ; sp = 0x7c00

+        mov   bp,sp         ; bp = 0x7c00

+

+        mov   ah,8                                ; ah = 8 - Get Drive Parameters Function

+        mov   byte ptr [bp+PhysicalDrive],dl      ; BBS defines that BIOS would pass the booting driver number to the loader through DL

+        int   13h                                 ; Get Drive Parameters

+        xor   ax,ax                   ; ax = 0

+        mov   al,dh                   ; al = dh

+        inc   al                      ; MaxHead = al + 1

+        push  ax                      ; 0000:7bfe = MaxHead

+        mov   al,cl                   ; al = cl

+        and   al,03fh                 ; MaxSector = al & 0x3f

+        push  ax                      ; 0000:7bfc = MaxSector

+

+; ****************************************************************************

+; Read GPT Header from hard disk to 0x0000:0x0800

+; ****************************************************************************

+        xor     ax, ax

+        mov     es, ax                            ; Read to 0x0000:0x0800

+        mov     di, 0800h                         ; Read to 0x0000:0x0800

+        mov     eax, 1                            ; Read LBA #1

+        mov     edx, 0                            ; Read LBA #1

+        mov     bx, 1                             ; Read 1 Block

+        push    es

+        call    ReadBlocks

+        pop     es

+

+; ****************************************************************************

+; Read Target GPT Entry from hard disk to 0x0000:0x0A00

+; ****************************************************************************

+        cmp   dword ptr es:[di], 020494645h       ; Check for "EFI "

+        jne   BadGpt

+        cmp   dword ptr es:[di + 4], 054524150h   ; Check for "PART"

+        jne   BadGpt

+        cmp   dword ptr es:[di + 8], 000010000h   ; Check Revision - 0x10000

+        jne   BadGpt

+

+        mov   eax, dword ptr es:[di + 84]         ; EAX = SizeOfPartitionEntry

+        mul   byte ptr [bp+GptPartitionIndicator] ; EAX = SizeOfPartitionEntry * GptPartitionIndicator

+        mov   edx, eax                            ; EDX = SizeOfPartitionEntry * GptPartitionIndicator

+        shr   eax, BLOCK_SHIFT                    ; EAX = (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE

+        and   edx, BLOCK_MASK                     ; EDX = Targer PartitionEntryLBA Offset

+                                                  ;     = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE

+        push  edx

+        mov   ecx, dword ptr es:[di + 72]         ; ECX = PartitionEntryLBA (Low)

+        mov   ebx, dword ptr es:[di + 76]         ; EBX = PartitionEntryLBA (High)

+        add   eax, ecx                            ; EAX = Target PartitionEntryLBA (Low)

+                                                  ;     = (PartitionEntryLBA + 

+                                                  ;        (SizeOfPartitionEntry * GptPartitionIndicator) / BLOCK_SIZE)

+        adc   edx, ebx                            ; EDX = Target PartitionEntryLBA (High)

+

+        mov   di, 0A00h                           ; Read to 0x0000:0x0A00

+        mov   bx, 1                               ; Read 1 Block

+        push  es

+        call  ReadBlocks

+        pop   es

+

+; ****************************************************************************

+; Read Target DBR from hard disk to 0x0000:0x7C00

+; ****************************************************************************

+        pop   edx                                 ; EDX = (SizeOfPartitionEntry * GptPartitionIndicator) % BLOCK_SIZE

+        add   di, dx                              ; DI = Targer PartitionEntryLBA Offset

+        cmp   dword ptr es:[di], 0C12A7328h       ; Check for EFI System Partition "C12A7328-F81F-11d2-BA4B-00A0C93EC93B"

+        jne   BadGpt

+        cmp   dword ptr es:[di + 4], 011d2F81Fh   ; 

+        jne   BadGpt

+        cmp   dword ptr es:[di + 8], 0A0004BBAh   ; 

+        jne   BadGpt

+        cmp   dword ptr es:[di + 0ch], 03BC93EC9h ; 

+        jne   BadGpt

+

+        mov   eax, dword ptr es:[di + 32]         ; EAX = StartingLBA (Low)

+        mov   edx, dword ptr es:[di + 36]         ; EDX = StartingLBA (High)

+        mov   di, 07C00h                          ; Read to 0x0000:0x7C00

+        mov   bx, 1                               ; Read 1 Block

+        call  ReadBlocks

+

+; ****************************************************************************

+; Transfer control to BootSector - Jump to 0x0000:0x7C00

+; ****************************************************************************

+        xor   ax, ax

+        push  ax                        ; PUSH 0x0000

+        mov   di, 07c00h

+        push  di                        ; PUSH 0x7C00

+        retf                            ; JMP 0x0000:0x7C00

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; EDX:EAX = Start LBA

+; BX      = Number of Blocks to Read (must < 127)

+; ES:DI   = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; si = DiskAddressPacket

+

+ReadBlocks:

+        pushad

+        push  ds

+        xor   cx, cx

+        mov   ds, cx

+        mov   bp, 0600h                         ; bp = 0x600

+        lea   si, [bp + OFFSET AddressPacket]   ; DS:SI = Disk Address Packet

+        mov   BYTE PTR ds:[si+2],bl             ;    02 = Number Of Block transfered

+        mov   WORD PTR ds:[si+4],di             ;    04 = Transfer Buffer Offset

+        mov   WORD PTR ds:[si+6],es             ;    06 = Transfer Buffer Segment

+        mov   DWORD PTR ds:[si+8],eax           ;    08 = Starting LBA (Low)

+        mov   DWORD PTR ds:[si+0ch],edx         ;    0C = Starting LBA (High)

+        mov   ah, 42h                           ; ah = Function 42

+        mov   dl,byte ptr [bp+PhysicalDrive]    ; dl = Drive Number

+        int   13h

+        jc    BadGpt

+        pop   ds

+        popad

+        ret

+

+; ****************************************************************************

+; Address Packet used by ReadBlocks

+; ****************************************************************************

+AddressPacket:

+        db    10h                       ; Size of address packet

+        db    00h                       ; Reserved.  Must be 0

+        db    01h                       ; Read blocks at a time (To be fixed each times)

+        db    00h                       ; Reserved.  Must be 0

+        dw    0000h                     ; Destination Address offset (To be fixed each times)

+        dw    0000h                     ; Destination Address segment (To be fixed each times)

+AddressPacketLba:

+        dd    0h, 0h                    ; Start LBA (To be fixed each times)

+AddressPacketEnd:

+

+; ****************************************************************************

+; ERROR Condition:

+; ****************************************************************************

+

+BadGpt:

+    mov  ax,0b800h

+    mov  es,ax

+    mov  ax, 060h

+    mov  ds, ax

+    lea  si, cs:[ErrorString]

+    mov  cx, 10

+    mov  di, 320

+    rep  movsw 

+Halt:

+    jmp   Halt

+

+StartString:

+    db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch

+ErrorString:

+    db 'G', 0ch, 'P', 0ch, 'T', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+; ****************************************************************************

+; PhysicalDrive - Used to indicate which disk to be boot

+;                 Can be patched by tool

+; ****************************************************************************

+    org   01B6h

+PhysicalDrive         db  80h

+

+; ****************************************************************************

+; GptPartitionIndicator - Used to indicate which GPT partition to be boot

+;                         Can be patched by tool

+; ****************************************************************************

+    org   01B7h

+GptPartitionIndicator db 0

+

+; ****************************************************************************

+; Unique MBR signature

+; ****************************************************************************

+    org   01B8h

+    db 'DUET'

+

+; ****************************************************************************

+; Unknown

+; ****************************************************************************

+    org   01BCh

+    dw 0

+

+; ****************************************************************************

+; PMBR Entry - Can be patched by tool

+; ****************************************************************************

+    org   01BEh

+    db 0          ; Boot Indicator

+    db 0ffh       ; Start Header

+    db 0ffh       ; Start Sector

+    db 0ffh       ; Start Track

+    db 0eeh       ; OS Type

+    db 0ffh       ; End Header

+    db 0ffh       ; End Sector

+    db 0ffh       ; End Track

+    dd 1          ; Starting LBA

+    dd 0FFFFFFFFh ; End LBA

+

+    org   01CEh

+    dd 0, 0, 0, 0

+    org   01DEh

+    dd 0, 0, 0, 0

+    org   01EEh

+    dd 0, 0, 0, 0

+

+; ****************************************************************************

+; Sector Signature

+; ****************************************************************************

+

+  org 01FEh

+SectorSignature:

+  dw        0aa55h      ; Boot Sector Signature

+

+  end 

+  

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/Makefile b/uefi/linaro-edk2/DuetPkg/BootSector/Makefile
new file mode 100644
index 0000000..cfee9a0
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/Makefile
@@ -0,0 +1,173 @@
+## @file

+#

+#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+#

+##

+

+BASETOOLS_DIR = $(EDK_TOOLS_PATH)\Bin\Win32

+

+#

+# Build Macro

+#

+ASSEMBLY_CODE_FILE_LIST = $(MODULE_DIR)\bootsect.asm \

+                          $(MODULE_DIR)\bs16.asm \

+                          $(MODULE_DIR)\bs32.asm \

+                          $(MODULE_DIR)\efi32.asm \

+                          $(MODULE_DIR)\Gpt.asm \

+                          $(MODULE_DIR)\Mbr.asm \

+                          $(MODULE_DIR)\start.asm \

+                          $(MODULE_DIR)\start16.asm \

+                          $(MODULE_DIR)\start32.asm 

+

+TARGET_FILES = $(OUTPUT_DIR)\bootsect.com \

+               $(OUTPUT_DIR)\bs16.com \

+               $(OUTPUT_DIR)\bs32.com \

+               $(OUTPUT_DIR)\Gpt.com \

+               $(OUTPUT_DIR)\Mbr.com \

+               $(OUTPUT_DIR)\Start.com \

+               $(OUTPUT_DIR)\Start16.com \

+               $(OUTPUT_DIR)\Start32.com \

+               $(OUTPUT_DIR)\Start64.com \

+               $(OUTPUT_DIR)\St16_64.com \

+               $(OUTPUT_DIR)\St32_64.com \

+               $(OUTPUT_DIR)\efi32.com2 \

+               $(OUTPUT_DIR)\efi64.com2 

+

+INC = 

+      

+

+#OBJECTS = 

+

+LIBS = 

+

+COMMON_DEPS = 

+

+all: $(TARGET_FILES)

+          

+#=============                

+$(OUTPUT_DIR)\bootsect.obj:$(MODULE_DIR)\bootsect.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\bootsect.obj" /FR"$(OUTPUT_DIR)\bootsect.txt" "$(MODULE_DIR)\bootsect.asm"

+             

+$(OUTPUT_DIR)\bootsect.com:$(OUTPUT_DIR)\bootsect.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bootsect.obj,$(OUTPUT_DIR)\bootsect.com,$(OUTPUT_DIR)\bootsect.map,,,

+

+#=============                

+

+$(OUTPUT_DIR)\bs16.obj:$(MODULE_DIR)\bs16.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\bs16.obj" "$(MODULE_DIR)\bs16.asm"

+             

+$(OUTPUT_DIR)\bs16.com:$(OUTPUT_DIR)\bs16.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs16.obj,$(OUTPUT_DIR)\bs16.com,$(OUTPUT_DIR)\bs16.map,,,

+

+#=============                

+

+$(OUTPUT_DIR)\bs32.obj:$(MODULE_DIR)\bs32.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\bs32.obj" "$(MODULE_DIR)\bs32.asm"

+             

+$(OUTPUT_DIR)\bs32.com:$(OUTPUT_DIR)\bs32.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\bs32.obj,$(OUTPUT_DIR)\bs32.com,$(OUTPUT_DIR)\bs32.map,,,

+

+#=============                

+

+$(OUTPUT_DIR)\Gpt.obj:$(MODULE_DIR)\Gpt.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Gpt.obj" "$(MODULE_DIR)\Gpt.asm"

+             

+$(OUTPUT_DIR)\Gpt.com:$(OUTPUT_DIR)\Gpt.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Gpt.obj,$(OUTPUT_DIR)\Gpt.com,$(OUTPUT_DIR)\Gpt.map,,,

+

+#=============                

+

+$(OUTPUT_DIR)\Mbr.obj:$(MODULE_DIR)\Mbr.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Mbr.obj" "$(MODULE_DIR)\Mbr.asm"

+             

+$(OUTPUT_DIR)\Mbr.com:$(OUTPUT_DIR)\Mbr.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Mbr.obj,$(OUTPUT_DIR)\Mbr.com,$(OUTPUT_DIR)\Mbr.map,,,

+

+#============

+

+$(OUTPUT_DIR)\Start.obj:$(MODULE_DIR)\Start.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Start.obj" "$(MODULE_DIR)\Start.asm"

+             

+$(OUTPUT_DIR)\Start.com:$(OUTPUT_DIR)\Start.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start.obj,$(OUTPUT_DIR)\Start.com,$(OUTPUT_DIR)\Start.map,,,

+  

+#=============     

+

+$(OUTPUT_DIR)\Start16.obj:$(MODULE_DIR)\Start16.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Start16.obj" "$(MODULE_DIR)\Start16.asm"

+             

+$(OUTPUT_DIR)\Start16.com:$(OUTPUT_DIR)\Start16.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start16.obj,$(OUTPUT_DIR)\Start16.com,$(OUTPUT_DIR)\Start16.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\Start32.obj:$(MODULE_DIR)\Start32.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Start32.obj" "$(MODULE_DIR)\Start32.asm"

+             

+$(OUTPUT_DIR)\Start32.com:$(OUTPUT_DIR)\Start32.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start32.obj,$(OUTPUT_DIR)\Start32.com,$(OUTPUT_DIR)\Start32.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\Start64.obj:$(MODULE_DIR)\Start64.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\Start64.obj" "$(MODULE_DIR)\Start64.asm"

+             

+$(OUTPUT_DIR)\Start64.com:$(OUTPUT_DIR)\Start64.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\Start64.obj,$(OUTPUT_DIR)\Start64.com,$(OUTPUT_DIR)\Start64.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\St16_64.obj:$(MODULE_DIR)\St16_64.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\St16_64.obj" "$(MODULE_DIR)\St16_64.asm"

+             

+$(OUTPUT_DIR)\St16_64.com:$(OUTPUT_DIR)\St16_64.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\St16_64.obj,$(OUTPUT_DIR)\St16_64.com,$(OUTPUT_DIR)\St16_64.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\St32_64.obj:$(MODULE_DIR)\St32_64.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\St32_64.obj" "$(MODULE_DIR)\St32_64.asm"

+             

+$(OUTPUT_DIR)\St32_64.com:$(OUTPUT_DIR)\St32_64.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\St32_64.obj,$(OUTPUT_DIR)\St32_64.com,$(OUTPUT_DIR)\St32_64.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\efi32.obj:$(MODULE_DIR)\efi32.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\efi32.obj" "$(MODULE_DIR)\efi32.asm"

+             

+$(OUTPUT_DIR)\efi32.com:$(OUTPUT_DIR)\efi32.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\efi32.obj,$(OUTPUT_DIR)\efi32.com,$(OUTPUT_DIR)\efi32.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\efi32.com2:$(OUTPUT_DIR)\efi32.com

+	$(BASETOOLS_DIR)\Split.exe -f $(OUTPUT_DIR)\efi32.com -t $(OUTPUT_DIR)\efi32.com2 -s 135168

+

+#=============

+

+$(OUTPUT_DIR)\efi64.obj:$(MODULE_DIR)\efi64.asm

+	"$(ASM)" /c /omf /Fo"$(OUTPUT_DIR)\efi64.obj" "$(MODULE_DIR)\efi64.asm"

+             

+$(OUTPUT_DIR)\efi64.com:$(OUTPUT_DIR)\efi64.obj

+	"$(ASMLINK)" /tiny $(OUTPUT_DIR)\efi64.obj,$(OUTPUT_DIR)\efi64.com,$(OUTPUT_DIR)\efi64.map,,,

+

+#=============

+

+$(OUTPUT_DIR)\efi64.com2:$(OUTPUT_DIR)\efi64.com

+	$(BASETOOLS_DIR)\Split.exe -f $(OUTPUT_DIR)\efi64.com -t $(OUTPUT_DIR)\efi64.com2 -s 135168

+

+    

+clean:

+	if exist $(DEBUG_DIR) rmdir /s /q $(DEBUG_DIR)

+	if exist $(OUTPUT_DIR) rmdir /s /q $(OUTPUT_DIR)

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.S b/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.S
new file mode 100644
index 0000000..65c97ea
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.S
@@ -0,0 +1,262 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials

+#*   are licensed and made available under the terms and conditions of the BSD License

+#*   which accompanies this distribution.  The full text of the license may be found at

+#*   http://opensource.org/licenses/bsd-license.php

+#*

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#*

+#*    Mbr.asm

+#*

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+    .code16 

+

+.equ                      BLOCK_SIZE, 0x0200

+.equ                      BLOCK_MASK, 0x01ff

+.equ                      BLOCK_SHIFT, 9

+

+# ****************************************************************************

+# Code loaded by BIOS at 0x0000:0x7C00

+# ****************************************************************************

+

+.org 0x0

+

+.global _start

+_start:

+

+# ****************************************************************************

+# Start Print

+# ****************************************************************************

+

+        movw $0xb800, %ax

+        movw %ax, %es

+        movw $0x7c0, %ax

+        movw %ax, %ds

+        leaw %cs:StartString, %si

+        movw $10, %cx

+        movw $160, %di

+        rep 

+        movsw

+

+# ****************************************************************************

+# Print over

+# ****************************************************************************

+

+# ****************************************************************************

+# Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600

+# ****************************************************************************

+        xorw  %ax, %ax                            # AX = 0x0000

+        movw  $0x7c00, %bx                        # BX = 0x7C00

+        movw  $0x600, %bp                         # BP = 0x0600

+        movw  $RelocatedStart, %si                # SI = Offset(RelocatedStart)

+        movw  $0x200, %cx                         # CX = 0x0200

+        subw  %si, %cx                            # CS = 0x0200 - Offset(RelocatedStart)

+        leaw  (%bp,%si,), %di                     # DI = 0x0600 + Offset(RelocatedStart)

+        leaw  (%bx,%si,), %si                     # BX = 0x7C00 + Offset(RelocatedStart)

+        movw  %ax, %ss                            # SS = 0x0000

+        movw  %bx, %sp                            # SP = 0x7C00

+        movw  %ax, %es                            # ES = 0x0000

+        movw  %ax, %ds                            # DS = 0x0000

+        pushw %ax                                 # PUSH 0x0000

+        pushw %di                                 # PUSH 0x0600 + Offset(RelocatedStart)

+        cld                                       # Clear the direction flag

+        rep

+        movsb                                     # Copy 0x0200 bytes from 0x7C00 to 0x0600

+        retl                                      # JMP 0x0000:0x0600 + Offset(RelocatedStart)

+

+# ****************************************************************************

+# Code relocated to 0x0000:0x0600

+# ****************************************************************************

+

+RelocatedStart: 

+# ****************************************************************************

+# Get Driver Parameters to 0x0000:0x7BFC

+# ****************************************************************************

+

+        xorw  %ax, %ax                            # AX = 0

+        movw  %ax, %ss                            # SS = 0

+        addw  $0x1000, %ax

+        movw  %ax, %ds

+

+        movw  $0x7c00, %sp                        # SP = 0x7c00

+        movw  %sp, %bp                            # BP = 0x7c00

+

+        movb  $8, %ah                             # AH = 8 - Get Drive Parameters Function

+        movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL

+        int   $0x13                               # Get Drive Parameters

+        xorw  %ax, %ax                            # AX = 0

+        movb  %dh, %al                            # AL = DH

+        incb  %al                                 # MaxHead = AL + 1

+        pushw %ax                                 # 0000:7bfe = MaxHead

+        movb  %cl, %al                            # AL = CL

+        andb  $0x3f, %al                          # MaxSector = AL & 0x3f

+        pushw %ax                                 # 0000:7bfc = MaxSector

+

+# ****************************************************************************

+# Read Target DBR from hard disk to 0x0000:0x7C00

+# ****************************************************************************

+

+        xorw  %ax, %ax

+        movb  MbrPartitionIndicator(%bp), %al          # AX = MbrPartitionIndex

+        cmpb  $0xff, %al                               # 0xFF means do legacy MBR boot

+        jnz   EfiDbr

+LegacyMbr: 

+        movl  $0x0000600, %eax                    # Assume LegacyMBR is backuped in Sector 6

+        jmp   StartReadTo7C00                     # EAX = Header/Sector/Tracker/Zero

+

+EfiDbr: 

+        cmpb  $4, %al                             # MbrPartitionIndex should < 4

+        jae   BadDbr

+        shlw  $4, %ax                             # AX  = MBREntrySize * Index

+        addw  $0x1be, %ax                         # AX  = MBREntryOffset

+        movw  %ax, %di                            # DI  = MBREntryOffset

+

+        # Here we don't use the C/H/S information provided by Partition table

+        #  but calculate C/H/S from LBA ourselves

+        #       Ci: Cylinder number

+        #       Hi: Header number

+        #       Si: Sector number

+        movl  %es:8(%bp,%di,), %eax               # Start LBA

+        movl  %eax, %edx

+        shrl  $16, %edx                           # DX:AX = Start LBA

+                                                  #       = Ci * (H * S) + Hi * S + (Si - 1)

+

+        # Calculate C/H/S according to LBA

+        movw  $0x7bfa, %bp

+        divw  2(%bp)                              # AX = Hi + H*Ci

+                                                  # DX = Si - 1

+        incw  %dx                                 # DX = Si

+        pushw %dx                                 # 0000:7bfa = Si  <----

+        xorw  %dx, %dx                            # DX:AX = Hi + H*Ci

+        divw  4(%bp)                              # AX = Ci         <----

+                                                  # DX = Hi         <----

+

+StartReadTo7C00: 

+

+        movb  (%bp), %cl                          # Si

+        movb  %al, %ch                            # Ci[0-7]

+        orb   %ah, %cl                            # Ci[8,9]

+        movw  $0x7c00, %bx                        # ES:BX = 0000:7C00h

+        movb  $0x2, %ah                           # Function 02h

+        movb  $1, %al                             # 1 Sector

+        movb  %dl, %dh                            # Hi

+        movw  $0x600, %bp

+        movb  PhysicalDrive(%bp), %dl             # Drive number

+        int   $0x13

+        jc    BadDbr

+

+

+

+# ****************************************************************************

+# Transfer control to BootSector - Jump to 0x0000:0x7C00

+# ****************************************************************************

+        xorw  %ax, %ax

+        pushw %ax                                 # PUSH 0x0000 - Segment

+        movw  $0x7c00, %di

+        pushw %di                                 # PUSH 0x7C00 - Offset

+        retl                                      # JMP 0x0000:0x7C00

+

+# ****************************************************************************

+# ERROR Condition:

+# ****************************************************************************

+

+BadDbr: 

+    pushw %ax

+    movw $0xb800, %ax

+    movw %ax, %es

+    movw $0x60, %ax

+    movw %ax, %ds

+    leaw %cs:ErrorString, %si

+    movw $320, %di

+    popw %ax

+    call A2C

+    movb %ah, 16(%si)

+    movb %al, 18(%si)

+    movw $10, %cx

+    rep

+    movsw

+Halt: 

+    jmp   Halt

+

+StartString: 

+.byte 'M', 0x0c, 'B', 0x0c, 'R', 0x0c, ' ', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c

+ErrorString: 

+.byte 'M', 0x0c, 'B', 0x0c, 'R', 0x0c, ' ', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, ':', 0x0c, '?', 0x0c, '?', 0x0c

+

+# ****************************************************************************

+# A2C - convert Ascii code stored in AH to character stored in AX

+# ****************************************************************************

+A2C: 

+    movb %ah, %al

+    shrb $4, %ah

+    andb $0xF, %al

+    addb '0', %ah

+    addb '0', %al

+

+    cmpb '9', %ah

+    jle  A2C_L1

+    addb $7, %ah

+A2C_L1: 

+

+    cmpb '9', %al

+    jle A2C_L2

+    addb $7, %al

+A2C_L2: 

+    ret

+

+

+# ****************************************************************************

+# PhysicalDrive - Used to indicate which disk to be boot

+#                 Can be patched by tool

+# ****************************************************************************

+.org   0x01B6

+PhysicalDrive:        .byte 0x80

+

+# ****************************************************************************

+# MbrPartitionIndicator - Used to indicate which MBR partition to be boot

+#                         Can be patched by tool

+#                         OxFF means boot to legacy MBR. (LBA OFFSET 6)

+# ****************************************************************************

+.org   0x01B7

+MbrPartitionIndicator: .byte 0

+

+# ****************************************************************************

+# Unique MBR signature

+# ****************************************************************************

+.org   0x01B8

+    .ascii "DUET"

+

+# ****************************************************************************

+# Unknown

+# ****************************************************************************

+.org   0x01BC

+    .word 0

+

+# ****************************************************************************

+# MBR Entry - To be patched

+# ****************************************************************************

+.org   0x01BE

+    .long 0,0,0,0

+.org   0x01CE

+    .long 0,0,0,0

+.org   0x01DE

+    .long 0,0,0,0

+.org   0x01EE

+    .long 0,0,0,0

+

+# ****************************************************************************

+# Sector Signature

+# ****************************************************************************

+

+.org 0x01FE

+SectorSignature: 

+  .word     0xaa55      # Boot Sector Signature

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.asm b/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.asm
new file mode 100644
index 0000000..b105c08
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/Mbr.asm
@@ -0,0 +1,261 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials

+;*   are licensed and made available under the terms and conditions of the BSD License

+;*   which accompanies this distribution.  The full text of the license may be found at

+;*   http://opensource.org/licenses/bsd-license.php

+;*

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+;*

+;*    Mbr.asm

+;*

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+    .model  small

+;   .dosseg

+    .stack

+    .486p

+    .code

+

+BLOCK_SIZE                EQU     0200h

+BLOCK_MASK                EQU     01ffh

+BLOCK_SHIFT               EQU     9

+

+; ****************************************************************************

+; Code loaded by BIOS at 0x0000:0x7C00

+; ****************************************************************************

+

+        org 0h

+Start:

+

+; ****************************************************************************

+; Start Print

+; ****************************************************************************

+

+        mov  ax,0b800h

+        mov  es,ax

+        mov  ax, 07c0h

+        mov  ds, ax

+        lea  si, cs:[StartString]

+        mov  cx, 10

+        mov  di, 160

+        rep  movsw

+

+; ****************************************************************************

+; Print over

+; ****************************************************************************

+

+; ****************************************************************************

+; Initialize segment registers and copy code at 0x0000:0x7c00 to 0x0000:0x0600

+; ****************************************************************************

+        xor   ax, ax                              ; AX = 0x0000

+        mov   bx, 07c00h                          ; BX = 0x7C00

+        mov   bp, 0600h                           ; BP = 0x0600

+        mov   si, OFFSET RelocatedStart           ; SI = Offset(RelocatedStart)

+        mov   cx, 0200h                           ; CX = 0x0200

+        sub   cx, si                              ; CS = 0x0200 - Offset(RelocatedStart)

+        lea   di, [bp+si]                         ; DI = 0x0600 + Offset(RelocatedStart)

+        lea   si, [bx+si]                         ; BX = 0x7C00 + Offset(RelocatedStart)

+        mov   ss, ax                              ; SS = 0x0000

+        mov   sp, bx                              ; SP = 0x7C00

+        mov   es,ax                               ; ES = 0x0000

+        mov   ds,ax                               ; DS = 0x0000

+        push  ax                                  ; PUSH 0x0000

+        push  di                                  ; PUSH 0x0600 + Offset(RelocatedStart)

+        cld                                       ; Clear the direction flag

+        rep   movsb                               ; Copy 0x0200 bytes from 0x7C00 to 0x0600

+        retf                                      ; JMP 0x0000:0x0600 + Offset(RelocatedStart)

+

+; ****************************************************************************

+; Code relocated to 0x0000:0x0600

+; ****************************************************************************

+

+RelocatedStart:

+; ****************************************************************************

+; Get Driver Parameters to 0x0000:0x7BFC

+; ****************************************************************************

+

+        xor   ax,ax                               ; AX = 0

+        mov   ss,ax                               ; SS = 0

+        add   ax,1000h

+        mov   ds,ax

+

+        mov   sp,07c00h                           ; SP = 0x7c00

+        mov   bp,sp                               ; BP = 0x7c00

+

+        mov   ah,8                                ; AH = 8 - Get Drive Parameters Function

+        mov   byte ptr [bp+PhysicalDrive],dl      ; BBS defines that BIOS would pass the booting driver number to the loader through DL

+        int   13h                                 ; Get Drive Parameters

+        xor   ax,ax                               ; AX = 0

+        mov   al,dh                               ; AL = DH

+        inc   al                                  ; MaxHead = AL + 1

+        push  ax                                  ; 0000:7bfe = MaxHead

+        mov   al,cl                               ; AL = CL

+        and   al,03fh                             ; MaxSector = AL & 0x3f

+        push  ax                                  ; 0000:7bfc = MaxSector

+

+; ****************************************************************************

+; Read Target DBR from hard disk to 0x0000:0x7C00

+; ****************************************************************************

+

+        xor   ax, ax

+        mov   al, byte ptr [bp+MbrPartitionIndicator]  ; AX = MbrPartitionIndex

+        cmp   al, 0ffh                                 ; 0xFF means do legacy MBR boot

+        jnz   EfiDbr

+LegacyMbr:

+        mov   eax, 00000600h                      ; Assume LegacyMBR is backuped in Sector 6

+        jmp   StartReadTo7C00                     ; EAX = Header/Sector/Tracker/Zero

+

+EfiDbr:

+        cmp   al, 4                               ; MbrPartitionIndex should < 4

+        jae   BadDbr

+        shl   ax, 4                               ; AX  = MBREntrySize * Index

+        add   ax, 1beh                            ; AX  = MBREntryOffset

+        mov   di, ax                              ; DI  = MBREntryOffset

+

+        ; Here we don't use the C/H/S information provided by Partition table

+        ;  but calculate C/H/S from LBA ourselves

+        ;       Ci: Cylinder number

+        ;       Hi: Header number

+        ;       Si: Sector number

+        mov   eax, dword ptr es:[bp + di + 8]     ; Start LBA

+        mov   edx, eax

+        shr   edx, 16                             ; DX:AX = Start LBA

+                                                  ;       = Ci * (H * S) + Hi * S + (Si - 1)

+

+        ; Calculate C/H/S according to LBA

+        mov   bp, 7bfah

+        div   word ptr [bp+2]                     ; AX = Hi + H*Ci

+                                                  ; DX = Si - 1

+        inc   dx                                  ; DX = Si

+        push  dx                                  ; 0000:7bfa = Si  <----

+        xor   dx, dx                              ; DX:AX = Hi + H*Ci

+        div   word ptr [bp+4]                     ; AX = Ci         <----

+                                                  ; DX = Hi         <----

+

+StartReadTo7C00:

+

+        mov   cl, byte ptr [bp]                   ; Si

+        mov   ch, al                              ; Ci[0-7]

+        or    cl, ah                              ; Ci[8,9]

+        mov   bx, 7c00h                           ; ES:BX = 0000:7C00h

+        mov   ah, 2h                              ; Function 02h

+        mov   al, 1                               ; 1 Sector

+        mov   dh, dl                              ; Hi

+        mov   bp, 0600h

+        mov   dl, byte ptr [bp + PhysicalDrive]   ; Drive number

+        int   13h

+        jc    BadDbr

+

+

+

+; ****************************************************************************

+; Transfer control to BootSector - Jump to 0x0000:0x7C00

+; ****************************************************************************

+        xor   ax, ax

+        push  ax                                  ; PUSH 0x0000 - Segment

+        mov   di, 07c00h

+        push  di                                  ; PUSH 0x7C00 - Offset

+        retf                                      ; JMP 0x0000:0x7C00

+

+; ****************************************************************************

+; ERROR Condition:

+; ****************************************************************************

+

+BadDbr:

+    push ax

+    mov  ax, 0b800h

+    mov  es, ax

+    mov  ax, 060h

+    mov  ds, ax

+    lea  si, cs:[ErrorString]

+    mov  di, 320

+    pop  ax

+    call A2C

+    mov  [si+16], ah

+    mov  [si+18], al

+    mov  cx, 10

+    rep  movsw

+Halt:

+    jmp   Halt

+

+StartString:

+    db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch

+ErrorString:

+    db 'M', 0ch, 'B', 0ch, 'R', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, ':', 0ch, '?', 0ch, '?', 0ch

+

+; ****************************************************************************

+; A2C - convert Ascii code stored in AH to character stored in AX

+; ****************************************************************************

+A2C:

+    mov  al, ah

+    shr  ah, 4

+    and  al, 0Fh

+    add  ah, '0'

+    add  al, '0'

+

+    cmp  ah, '9'

+    jle  @f

+    add  ah, 7

+@@:

+

+    cmp al, '9'

+    jle @f

+    add al, 7

+@@:

+    ret

+

+

+; ****************************************************************************

+; PhysicalDrive - Used to indicate which disk to be boot

+;                 Can be patched by tool

+; ****************************************************************************

+    org   01B6h

+PhysicalDrive         db  80h

+

+; ****************************************************************************

+; MbrPartitionIndicator - Used to indicate which MBR partition to be boot

+;                         Can be patched by tool

+;                         OxFF means boot to legacy MBR. (LBA OFFSET 6)

+; ****************************************************************************

+    org   01B7h

+MbrPartitionIndicator db 0

+

+; ****************************************************************************

+; Unique MBR signature

+; ****************************************************************************

+    org   01B8h

+    db 'DUET'

+

+; ****************************************************************************

+; Unknown

+; ****************************************************************************

+    org   01BCh

+    dw 0

+

+; ****************************************************************************

+; MBR Entry - To be patched

+; ****************************************************************************

+    org   01BEh

+    dd 0, 0, 0, 0

+    org   01CEh

+    dd 0, 0, 0, 0

+    org   01DEh

+    dd 0, 0, 0, 0

+    org   01EEh

+    dd 0, 0, 0, 0

+

+; ****************************************************************************

+; Sector Signature

+; ****************************************************************************

+

+  org 01FEh

+SectorSignature:

+  dw        0aa55h      ; Boot Sector Signature

+

+  end

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Gpt.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Gpt.com
new file mode 100644
index 0000000..f055fd7
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Gpt.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Mbr.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Mbr.com
new file mode 100644
index 0000000..ca292a0
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Mbr.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Readme.txt b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Readme.txt
new file mode 100644
index 0000000..55dd8cd
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Readme.txt
@@ -0,0 +1,8 @@
+These binaries are used to make the bootable floppy or usb disk. 

+The binaries of boot sector are built from DuetPkg\Bootsector\BootSector.inf at r8617 with following steps:

+1) enter edk2 workspace directory from command line windows.

+2) run "edksetup.bat"

+3) run "build -p DuetPkg/DuetPkg.dsc -a IA32 -m DuetPkg/BootSector/BootSector.inf"

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/St16_64.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/St16_64.com
new file mode 100644
index 0000000..dbb4a9a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/St16_64.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/St32_64.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/St32_64.com
new file mode 100644
index 0000000..68b6c76
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/St32_64.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start.com
new file mode 100644
index 0000000..0fd19a1
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start16.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start16.com
new file mode 100644
index 0000000..b2d77c1
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start16.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start32.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start32.com
new file mode 100644
index 0000000..ac0e3cb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start32.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start64.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start64.com
new file mode 100644
index 0000000..326e3fe
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/Start64.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/bootsect.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bootsect.com
new file mode 100644
index 0000000..079978e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bootsect.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs16.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs16.com
new file mode 100644
index 0000000..be40ba8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs16.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs32.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs32.com
new file mode 100644
index 0000000..9cd368a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/bs32.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com
new file mode 100644
index 0000000..4bcd83e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com2 b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com2
new file mode 100644
index 0000000..05522ec
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi32.com2
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com
new file mode 100644
index 0000000..e534132
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com2 b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com2
new file mode 100644
index 0000000..689f4ab
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bin/efi64.com2
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.S b/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.S
new file mode 100644
index 0000000..5993a1a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.S
@@ -0,0 +1,303 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*   bootsect.S

+#*  

+#*   bootsect.S is built as 16-bit binary file in 512 bytes and patched to disk/partition's 

+#*   first section - boot sector. 

+#*

+#*   The startup sequence for DUET disk boot sector is:

+#*

+#*   1, LegacyBios check 0xAA55 signature at boot sectore offset 0x1FE to judget 

+#*      whether disk/partition is bootable.

+#*   2, LegacyBios will load boot sector to 0x7c00 in real mode, pass BPB data and

+#*      hand off control to 0x7c00 code.

+#*   3, boot sector code simply parse FAT format in boot disk and find EfiLdr binary file 

+#*      and EfiVar.bin if exists. For first boot, EfiVar.bin does not exist.

+#*   4, boot sector load the first sector of EfiLdr binary which is start.com to

+#*      0x2000:0x0000 address.

+#*   5, boot sector handoff control to 0x2000:0x0000 for start.com binary.

+#*

+#------------------------------------------------------------------------------

+

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                      FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                      FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                      BLOCK_SIZE, 0x0200

+.equ                      BLOCK_MASK, 0x01ff

+.equ                      BLOCK_SHIFT, 9

+                                               # "EFILDR_____"

+.equ                      LOADER_FILENAME_PART1, 0x04c494645    # "EFIL"

+.equ                      LOADER_FILENAME_PART2, 0x020205244    # "DR__"

+.equ                      LOADER_FILENAME_PART3, 0x020202020    # "____"

+

+        .org 0x0

+.global _start

+_start:

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst                  - 3 bytes

+  nop

+

+OemId:              .ascii   "INTEL   "       # OemId               - 8 bytes

+# BPB data below will be fixed by tool

+SectorSize:         .word  0                  # Sector Size         - 16 bits

+SectorsPerCluster:  .byte  0                  # Sector Per Cluster  - 8 bits

+ReservedSectors:    .word  0                  # Reserved Sectors    - 16 bits

+NoFats:             .byte  0                  # Number of FATs      - 8 bits

+RootEntries:        .word  0                  # Root Entries        - 16 bits

+Sectors:            .word  0                  # Number of Sectors   - 16 bits

+Media:              .byte  0                  # Media               - 8 bits  - ignored

+SectorsPerFat:      .word  0                  # Sectors Per FAT     - 16 bits

+SectorsPerTrack:    .word  0                  # Sectors Per Track   - 16 bits - ignored

+Heads:              .word  0                  # Heads               - 16 bits - ignored

+HiddenSectors:      .long  0                  # Hidden Sectors      - 32 bits - ignored

+LargeSectors:       .long  0                  # Large Sectors       - 32 bits 

+PhysicalDrive:      .byte  0                  # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:        .byte  0                  # Current Head        - 8 bits

+Signature:          .byte  0                  # Signature           - 8 bits  - ignored

+VolId:              .ascii "    "             # Volume Serial Number- 4 bytes

+FatLabel:           .ascii "           "      # Label               - 11 bytes

+SystemId:           .ascii "FAT12   "         # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+

+# ****************************************************************************

+# Start Print

+# ****************************************************************************

+  movw $StartString, %si

+  call PrintString

+

+# ****************************************************************************

+# Print over

+# ****************************************************************************

+

+  movw  %cs, %ax      # ax = 0

+  movw  %ax, %ss      # ss = 0

+  addw  $0x1000, %ax

+  movw  %ax, %ds

+

+  movw  $0x7c00, %sp  # sp = 0x7c00

+  movw  %sp, %bp      # bp = 0x7c00

+

+  movb  $8, %ah                             # ah = 8 - Get Drive Parameters Function

+  movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   $0x13                               # Get Drive Parameters

+  xorw  %ax, %ax                # ax = 0

+  movb  %dh, %al                # al = dh

+  incb  %al                     # MaxHead = al + 1

+  pushw %ax                     # 0000:7bfe = MaxHead

+  movb  %cl, %al                # al = cl

+  andb  $0x3f, %al              # MaxSector = al & 0x3f

+  pushw %ax                     # 0000:7bfc = MaxSector

+

+  cmpw  $0xaa55, SectorSignature(%bp)         # Verify Boot Sector Signature

+  jne   BadBootSector

+  movw  RootEntries(%bp), %cx             # cx = RootEntries

+  shlw  $FAT_DIRECTORY_ENTRY_SHIFT, %cx   # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  andw  $BLOCK_MASK, %bx                  # See if it is an even number of sectors long

+  jne   BadBootSector                     # If is isn't, then the boot sector is bad.

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  shrw  $BLOCK_SHIFT, %bx                 # bx = size of Root Directory in sectors

+  movb  NoFats(%bp), %al                  # al = NoFats

+  xorb  %ah, %ah                          # ah = 0  ==> ax = NoFats

+  mulw  SectorsPerFat(%bp)                # ax = NoFats * SectorsPerFat

+  addw  ReservedSectors(%bp), %ax         # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  pushw %ds

+  popw  %es

+  xorw  %di, %di                          # Store directory in es:di = 1000:0000

+  call  ReadBlocks                        # Read entire Root Directory

+  addw  %bx, %ax                          # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)

+  movw  %ax, (%bp)                        # Save FirstClusterLBA (FirstDataSector) for later use

+

+  # dx - variable storage (initial value is 0)

+  # bx - loader (initial value is 0)

+  xorw  %dx, %dx

+  xorw  %bx, %bx

+

+FindEFILDR: 

+  cmpl   $LOADER_FILENAME_PART1, (%di)        # Compare to "EFIL"

+  jne   FindVARSTORE

+  cmpl   $LOADER_FILENAME_PART2, 4(%di) 

+  jne   FindVARSTORE

+  cmpl   $LOADER_FILENAME_PART3, 7(%di) 

+  jne   FindVARSTORE

+  movw  26(%di), %bx                      # bx = Start Cluster for EFILDR  <----------------------------------

+  testw %dx, %dx

+  je    FindNext                          # Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE: 

+  ## if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmpl  $0x56494645, (%di)                # Compare to "EFIV"

+  jne   FindNext

+  cmpl  $0x20205241, 4(%di)               # Compare to "AR  "

+  jne   FindNext

+  cmpl  $0x4e494220, 7(%di)               # Compare to " BIN"

+  jne   FindNext

+  movw  %di, %dx                          # dx = Offset of Start Cluster for Efivar.bin <---------------------

+  addw  $26, %dx

+  testw %bx, %bx

+  je    FindNext                          # Efildr is not loaded

+  jmp   FoundAll

+

+FindNext: 

+  # go to next find

+  addw  $FAT_DIRECTORY_ENTRY_SIZE, %di    # Increment di

+  subw  $FAT_DIRECTORY_ENTRY_SIZE, %cx    # Decrement cx

+  # TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll: 

+FoundEFILDR: 

+  movw    %bx, %cx                            # cx = Start Cluster for EFILDR  <----------------------------------

+  movw    %cs, %ax                            # Destination = 2000:0000

+  addw    $0x2000, %ax

+  movw    %ax, %es

+  xorw    %di, %di

+ReadFirstClusterOfEFILDR: 

+  movw    %cx, %ax                            # ax = StartCluster

+  subw    $2, %ax                             # ax = StartCluster - 2

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+  pushw   %dx

+  mulw    %bx

+  popw    %dx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+  addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = Number of Sectors in a cluster

+  pushw   %es

+  call    ReadBlocks

+  popw    %ax

+JumpIntoFirstSectorOfEFILDR: 

+  movw    %ax, JumpSegment(%bp)

+JumpFarInstruction: 

+  .byte   0xea

+JumpOffset: 

+  .word   0x000

+JumpSegment: 

+  .word   0x2000

+

+

+PrintString: 

+  movw $0xb800, %ax

+  movw %ax, %es

+  movw $0x7c0, %ax

+  movw %ax, %ds

+  movw $7, %cx

+  movw $160, %di

+  rep

+  movsw

+  ret

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+  pusha

+  addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA

+  addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+  movl    %eax, %esi                          # esi = Start LBA

+  movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+  movw    $0x7bfc, %bp                        # bp = 0x7bfc

+  movl    %esi, %eax                          # eax = Start LBA

+  xorl    %edx, %edx                          # edx = 0

+  movzwl  (%bp), %ebx                         # bx = MaxSector

+  divl    %ebx                                # ax = StartLBA / MaxSector

+  incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+  subw    %dx, %bx                            # bx = MaxSector - Sector

+  incw    %bx                                 # bx = MaxSector - Sector + 1

+  cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+  pushw   %cx

+  movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+  xorw    %dx, %dx                            # dx = 0

+  divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                              # dx = ax % (MaxHead + 1) = Head

+

+  pushw   %bx                                 # Save number of blocks to transfer

+  movb    %dl, %dh                            # dh = Head

+  movw    $0x7c00, %bp                        # bp = 0x7c00

+  movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+  movb    %al, %ch                            # ch = Cylinder

+  movb    %bl, %al                            # al = Blocks

+  movb    $2, %ah                             # ah = Function 2

+  movw    %di, %bx                            # es:bx = Buffer address

+  int     $0x13

+  jc      DiskError

+  popw    %bx

+  popw    %cx

+  movzwl  %bx, %ebx

+  addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+  subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+  movw    %es, %ax

+  shlw    $(BLOCK_SHIFT-4), %bx

+  addw    %bx, %ax

+  movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmpw    $0, %cx

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+# ****************************************************************************

+# ERROR Condition:

+# ****************************************************************************

+NotFoundAll: 

+  ## if we found EFILDR, continue

+  testw %bx, %bx

+  jne  FoundEFILDR

+BadBootSector: 

+DiskError: 

+  movw $ErrorString, %si

+  call PrintString

+Halt: 

+  jmp   Halt

+

+StartString: 

+  .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c

+ErrorString: 

+  .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c

+

+# ****************************************************************************

+# LBA Offset for BootSector, need patched by tool for HD boot.

+# ****************************************************************************

+

+  .org 0x01fa   # Comment it for pass build. Should optimise code size. 

+LBAOffsetForBootSector: 

+  .long     0x0

+

+# ****************************************************************************

+# Sector Signature

+# ****************************************************************************

+

+  .org 0x01fe    # Comment it for pass build.

+SectorSignature: 

+  .word     0xaa55      # Boot Sector Signature

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.asm b/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.asm
new file mode 100644
index 0000000..3366b7a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bootsect.asm
@@ -0,0 +1,301 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*   bootsect.asm

+;*    

+;*   bootsect.asm is built as 16-bit binary file in 512 bytes and patched to disk/partition's 

+;*   first section - boot sector. 

+;*

+;*   The startup sequence for DUET disk boot sector is:

+;*

+;*   1, LegacyBios check 0xAA55 signature at boot sectore offset 0x1FE to judget 

+;*      whether disk/partition is bootable.

+;*   2, LegacyBios will load boot sector to 0x7c00 in real mode, pass BPB data and

+;*      hand off control to 0x7c00 code.

+;*   3, boot sector code simply parse FAT format in boot disk and find EfiLdr binary file 

+;*      and EfiVar.bin if exists. For first boot, EfiVar.bin does not exist.

+;*   4, boot sector load the first sector of EfiLdr binary which is start.com to

+;*      0x2000:0x0000 address.

+;*   5, boot sector handoff control to 0x2000:0x0000 for start.com binary.

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE  EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT EQU     5

+BLOCK_SIZE                EQU     0200h

+BLOCK_MASK                EQU     01ffh

+BLOCK_SHIFT               EQU     9

+                                               ; "EFILDR_____"

+LOADER_FILENAME_PART1     EQU     04c494645h   ; "EFIL"

+LOADER_FILENAME_PART2     EQU     020205244h   ; "DR__"

+LOADER_FILENAME_PART3     EQU     020202020h   ; "____"

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst                  - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+; BPB data below will be fixed by tool

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+Id                db  "    "        ; Id                  - 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT12   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+

+; ****************************************************************************

+; Start Print

+; ****************************************************************************

+  lea  si, cs:[StartString]

+  call PrintString

+

+; ****************************************************************************

+; Print over

+; ****************************************************************************

+

+  mov   ax,cs         ; ax = 0

+  mov   ss,ax         ; ss = 0

+  add   ax,1000h

+  mov   ds,ax

+

+  mov   sp,07c00h     ; sp = 0x7c00

+  mov   bp,sp         ; bp = 0x7c00

+

+  mov   ah,8                                ; ah = 8 - Get Drive Parameters Function

+  mov   byte ptr [bp+PhysicalDrive],dl      ; BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   13h                                 ; Get Drive Parameters

+  xor   ax,ax                               ; ax = 0

+  mov   al,dh                               ; al = dh (number of sides (0 based))

+  inc   al                                  ; MaxHead = al + 1

+  push  ax                                  ; 0000:7bfe = MaxHead

+  mov   al,cl                               ; al = cl (CL = sectors per track)

+  and   al,03fh                             ; MaxSector = al & 0x3f

+  push  ax                                  ; 0000:7bfc = MaxSector

+

+  cmp   word ptr [bp+SectorSignature],0aa55h  ; Verify Boot Sector Signature

+  jne   BadBootSector

+  mov   cx,word ptr [bp+RootEntries]      ; cx = RootEntries

+  shl   cx,FAT_DIRECTORY_ENTRY_SHIFT      ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  and   bx,BLOCK_MASK                     ; See if it is an even number of sectors long

+  jne   BadBootSector                     ; If is isn't, then the boot sector is bad.

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  shr   bx,BLOCK_SHIFT                    ; bx = size of Root Directory in sectors

+  mov   al,byte ptr [bp+NoFats]           ; al = NoFats

+  xor   ah,ah                             ; ah = 0  ==> ax = NoFats

+  mul   word ptr [bp+SectorsPerFat]       ; ax = NoFats * SectorsPerFat

+  add   ax,word ptr [bp+ReservedSectors]  ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  push  ds

+  pop   es

+  xor   di,di                             ; Store directory in es:di = 1000:0000

+  call  ReadBlocks                        ; Read entire Root Directory

+  add   ax,bx                             ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)

+  mov   word ptr [bp],ax                  ; Save FirstClusterLBA (FirstDataSector) for later use

+

+  ; dx - variable storage (initial value is 0)

+  ; bx - loader (initial value is 0)

+  xor   dx, dx

+  xor   bx, bx

+

+FindEFILDR:

+  cmp   dword ptr [di],LOADER_FILENAME_PART1         ; Compare to "EFIL"

+  jne   FindVARSTORE

+  cmp   dword ptr [di+4],LOADER_FILENAME_PART2

+  jne   FindVARSTORE

+  cmp   dword ptr [di+7],LOADER_FILENAME_PART3

+  jne   FindVARSTORE

+  mov   bx, word ptr [di+26]              ; bx = Start Cluster for EFILDR  <----------------------------------

+  test  dx, dx

+  je    FindNext                          ; Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE:

+  ; if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmp   dword ptr [di], 056494645h        ; Compare to "EFIV"

+  jne   FindNext

+  cmp   dword ptr [di+4], 020205241h      ; Compare to "AR  "

+  jne   FindNext

+  cmp   dword ptr [di+7], 04e494220h      ; Compare to " BIN"

+  jne   FindNext

+  mov   dx, di                            ; dx = Offset of Start Cluster for Efivar.bin <---------------------

+  add   dx, 26

+  test  bx, bx

+  je    FindNext                          ; Efildr is not loaded

+  jmp   FoundAll

+  

+FindNext:

+  ; go to next find

+  add   di,FAT_DIRECTORY_ENTRY_SIZE       ; Increment di

+  sub   cx,FAT_DIRECTORY_ENTRY_SIZE       ; Decrement cx

+  ; TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll:

+FoundEFILDR:                                  ; 0x7cfe

+  mov     cx,bx                               ; cx = Start Cluster for EFILDR  <----------------------------------

+  mov     ax,cs                               ; Destination = 2000:0000

+  add     ax,2000h

+  mov     es,ax

+  xor     di,di

+ReadFirstClusterOfEFILDR:

+  mov     ax,cx                               ; ax = StartCluster

+  sub     ax,2                                ; ax = StartCluster - 2

+  xor     bh,bh                               

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+  push    dx

+  mul     bx

+  pop     dx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+  add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xor     bh,bh

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = Number of Sectors in a cluster

+  push    es

+  call    ReadBlocks

+  pop     ax

+JumpIntoFirstSectorOfEFILDR:

+  mov     word ptr [bp+JumpSegment],ax        ; 0x7d26

+JumpFarInstruction:                           ; 0x7d2a

+  db      0eah

+JumpOffset:

+  dw      0000h

+JumpSegment:

+  dw      2000h

+

+

+PrintString:

+  mov  ax,0b800h

+  mov  es,ax

+  mov  ax, 07c0h

+  mov  ds, ax

+  mov  cx, 7

+  mov  di, 160

+  rep  movsw

+  ret

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+  pusha

+  add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+  add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+  mov     esi,eax                             ; esi = Start LBA

+  mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+  mov     bp,07bfch                           ; bp = 0x7bfc

+  mov     eax,esi                             ; eax = Start LBA

+  xor     edx,edx                             ; edx = 0

+  movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+  div     ebx                                 ; ax = StartLBA / MaxSector

+  inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+  sub     bx,dx                               ; bx = MaxSector - Sector

+  inc     bx                                  ; bx = MaxSector - Sector + 1

+  cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+  push    cx

+  mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+  xor     dx,dx                               ; dx = 0

+  div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                              ; dx = ax % (MaxHead + 1) = Head

+

+  push    bx                                  ; Save number of blocks to transfer

+  mov     dh,dl                               ; dh = Head

+  mov     bp,07c00h                           ; bp = 0x7c00

+  mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+  mov     ch,al                               ; ch = Cylinder

+  mov     al,bl                               ; al = Blocks

+  mov     ah,2                                ; ah = Function 2

+  mov     bx,di                               ; es:bx = Buffer address

+  int     013h

+  jc      DiskError

+  pop     bx

+  pop     cx

+  movzx   ebx,bx

+  add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+  sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+  mov     ax,es

+  shl     bx,(BLOCK_SHIFT-4)

+  add     ax,bx

+  mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmp     cx,0

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+; ****************************************************************************

+; ERROR Condition:

+; ****************************************************************************

+NotFoundAll:                            ; 0x7da6

+  ; if we found EFILDR, continue

+  test bx,bx

+  jne  FoundEFILDR

+BadBootSector:

+DiskError:

+  lea  si, cs:[ErrorString]

+  call PrintString

+Halt:

+  jmp   Halt

+

+StartString:

+  db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch

+ErrorString:

+  db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+; ****************************************************************************

+; LBA Offset for BootSector, need patched by tool for HD boot.

+; ****************************************************************************

+

+  org 01fah

+LBAOffsetForBootSector:

+  dd        0h

+

+; ****************************************************************************

+; Sector Signature

+; ****************************************************************************

+

+  org 01feh

+SectorSignature:

+  dw        0aa55h      ; Boot Sector Signature

+

+  end 

+  

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bs16.S b/uefi/linaro-edk2/DuetPkg/BootSector/bs16.S
new file mode 100644
index 0000000..039e256
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bs16.S
@@ -0,0 +1,291 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    bs16.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+        #.MODEL small

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                      FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                      FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                      BLOCK_SIZE, 0x0200

+.equ                      BLOCK_MASK, 0x01ff

+.equ                      BLOCK_SHIFT, 9

+                                               # "EFILDR_____"

+.equ                      LOADER_FILENAME_PART1, 0x04c494645    # "EFIL"

+.equ                      LOADER_FILENAME_PART2, 0x036315244    # "DR16"

+.equ                      LOADER_FILENAME_PART3, 0x020202036    # "6___"

+

+        .org 0x0

+.global _start

+_start:

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst                  - 3 bytes

+  nop

+

+OemId:              .ascii   "INTEL   "       # OemId               - 8 bytes

+# BPB data below will be fixed by tool

+SectorSize:         .word  0                  # Sector Size         - 16 bits

+SectorsPerCluster:  .byte  0                  # Sector Per Cluster  - 8 bits

+ReservedSectors:    .word  0                  # Reserved Sectors    - 16 bits

+NoFats:             .byte  0                  # Number of FATs      - 8 bits

+RootEntries:        .word  0                  # Root Entries        - 16 bits

+Sectors:            .word  0                  # Number of Sectors   - 16 bits

+Media:              .byte  0                  # Media               - 8 bits  - ignored

+SectorsPerFat:      .word  0                  # Sectors Per FAT     - 16 bits

+SectorsPerTrack:    .word  0                  # Sectors Per Track   - 16 bits - ignored

+Heads:              .word  0                  # Heads               - 16 bits - ignored

+HiddenSectors:      .long  0                  # Hidden Sectors      - 32 bits - ignored

+LargeSectors:       .long  0                  # Large Sectors       - 32 bits 

+PhysicalDrive:      .byte  0                  # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:        .byte  0                  # Current Head        - 8 bits

+Signature:          .byte  0                  # Signature           - 8 bits  - ignored

+VolId:              .ascii "    "             # Volume Serial Number- 4 bytes

+FatLabel:           .ascii "           "      # Label               - 11 bytes

+SystemId:           .ascii "FAT12   "         # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+

+# ****************************************************************************

+# Start Print

+# ****************************************************************************

+  movw $StartString, %si

+  call PrintString

+

+# ****************************************************************************

+# Print over

+# ****************************************************************************

+

+  movw  %cs, %ax      # ax = 0

+  movw  %ax, %ss      # ss = 0

+  addw  $0x1000, %ax

+  movw  %ax, %ds

+

+  movw  $0x7c00, %sp  # sp = 0x7c00

+  movw  %sp, %bp      # bp = 0x7c00

+

+  movb  $8, %ah                             # ah = 8 - Get Drive Parameters Function

+  movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   $0x13                               # Get Drive Parameters

+  xorw  %ax, %ax                # ax = 0

+  movb  %dh, %al                # al = dh

+  incb  %al                     # MaxHead = al + 1

+  pushw %ax                     # 0000:7bfe = MaxHead

+  movb  %cl, %al                # al = cl

+  andb  $0x3f, %al              # MaxSector = al & 0x3f

+  pushw %ax                     # 0000:7bfc = MaxSector

+

+  cmpw  $0xaa55, SectorSignature(%bp)         # Verify Boot Sector Signature

+  jne   BadBootSector

+  movw  RootEntries(%bp), %cx             # cx = RootEntries

+  shlw  $FAT_DIRECTORY_ENTRY_SHIFT, %cx   # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  andw  $BLOCK_MASK, %bx                  # See if it is an even number of sectors long

+  jne   BadBootSector                     # If is isn't, then the boot sector is bad.

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  shrw  $BLOCK_SHIFT, %bx                 # bx = size of Root Directory in sectors

+  movb  NoFats(%bp), %al                  # al = NoFats

+  xorb  %ah, %ah                          # ah = 0  ==> ax = NoFats

+  mulw  SectorsPerFat(%bp)                # ax = NoFats * SectorsPerFat

+  addw  ReservedSectors(%bp), %ax         # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  pushw %ds

+  popw  %es

+  xorw  %di, %di                          # Store directory in es:di = 1000:0000

+  call  ReadBlocks                        # Read entire Root Directory

+  addw  %bx, %ax                          # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)

+  movw  %ax, (%bp)                        # Save FirstClusterLBA (FirstDataSector) for later use

+

+  # dx - variable storage (initial value is 0)

+  # bx - loader (initial value is 0)

+  xorw  %dx, %dx

+  xorw  %bx, %bx

+

+FindEFILDR: 

+  cmpl   $LOADER_FILENAME_PART1, (%di)        # Compare to "EFIL"

+  jne   FindVARSTORE

+  cmpl   $LOADER_FILENAME_PART2, 4(%di) 

+  jne   FindVARSTORE

+  cmpl   $LOADER_FILENAME_PART3, 7(%di) 

+  jne   FindVARSTORE

+  movw  26(%di), %bx                      # bx = Start Cluster for EFILDR  <----------------------------------

+  testw %dx, %dx

+  je    FindNext                          # Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE: 

+  ##if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmpl  $0x56494645, (%di)                # Compare to "EFIV"

+  jne   FindNext

+  cmpl  $0x20205241, 4(%di)               # Compare to "AR  "

+  jne   FindNext

+  cmpl  $0x4e494220, 7(%di)               # Compare to " BIN"

+  jne   FindNext

+  movw  %di, %dx                          # dx = Offset of Start Cluster for Efivar.bin <---------------------

+  addw  $26, %dx

+  testw %bx, %bx

+  je    FindNext                          # Efildr is not loaded

+  jmp   FoundAll

+

+FindNext: 

+  # go to next find

+  addw  $FAT_DIRECTORY_ENTRY_SIZE, %di    # Increment di

+  subw  $FAT_DIRECTORY_ENTRY_SIZE, %cx    # Decrement cx

+  # TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll: 

+FoundEFILDR: 

+  movw    %bx, %cx                            # cx = Start Cluster for EFILDR  <----------------------------------

+  movw    %cs, %ax                            # Destination = 2000:0000

+  addw    $0x2000, %ax

+  movw    %ax, %es

+  xorw    %di, %di

+ReadFirstClusterOfEFILDR: 

+  movw    %cx, %ax                            # ax = StartCluster

+  subw    $2, %ax                             # ax = StartCluster - 2

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+  pushw   %dx

+  mulw    %bx

+  popw    %dx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+  addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = Number of Sectors in a cluster

+  pushw   %es

+  call    ReadBlocks

+  popw    %ax

+JumpIntoFirstSectorOfEFILDR: 

+  movw    %ax, JumpSegment(%bp)

+JumpFarInstruction: 

+  .byte   0xea

+JumpOffset: 

+  .word   0x000

+JumpSegment: 

+  .word   0x2000

+

+

+PrintString: 

+  movw $0xb800, %ax

+  movw %ax, %es

+  movw $0x7c0, %ax

+  movw %ax, %ds

+  movw $7, %cx

+  movw $160, %di

+  rep

+  movsw

+  ret

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+  pusha

+  addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA

+  addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+  movl    %eax, %esi                          # esi = Start LBA

+  movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+  movw    $0x7bfc, %bp                        # bp = 0x7bfc

+  movl    %esi, %eax                          # eax = Start LBA

+  xorl    %edx, %edx                          # edx = 0

+  movzwl  (%bp), %ebx                         # bx = MaxSector

+  divl    %ebx                                # ax = StartLBA / MaxSector

+  incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+  subw    %dx, %bx                            # bx = MaxSector - Sector

+  incw    %bx                                 # bx = MaxSector - Sector + 1

+  cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+  pushw   %cx

+  movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+  xorw    %dx, %dx                            # dx = 0

+  divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                              # dx = ax % (MaxHead + 1) = Head

+

+  pushw   %bx                                 # Save number of blocks to transfer

+  movb    %dl, %dh                            # dh = Head

+  movw    $0x7c00, %bp                        # bp = 0x7c00

+  movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+  movb    %al, %ch                            # ch = Cylinder

+  movb    %bl, %al                            # al = Blocks

+  movb    $2, %ah                             # ah = Function 2

+  movw    %di, %bx                            # es:bx = Buffer address

+  int     $0x13

+  jc      DiskError

+  popw    %bx

+  popw    %cx

+  movzwl  %bx, %ebx

+  addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+  subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+  movw    %es, %ax

+  shlw    $(BLOCK_SHIFT-4),%bx

+  addw    %bx, %ax

+  movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmpw    $0, %cx

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+# ****************************************************************************

+# ERROR Condition:

+# ****************************************************************************

+NotFoundAll: 

+  ## if we found EFILDR, continue

+  testw %bx, %bx

+  jne  FoundEFILDR

+BadBootSector: 

+DiskError: 

+  movw $ErrorString, %si

+  call PrintString

+Halt: 

+  jmp   Halt

+

+StartString: 

+  .byte  'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c, '!', 0x0c

+ErrorString: 

+  .byte  'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c

+

+# ****************************************************************************

+# LBA Offset for BootSector, need patched by tool for HD boot.

+# ****************************************************************************

+

+  .org 0x01fa

+LBAOffsetForBootSector: 

+  .long     0x0

+

+# ****************************************************************************

+# Sector Signature

+# ****************************************************************************

+

+  .org 0x01fe

+SectorSignature: 

+  .word     0xaa55      # Boot Sector Signature

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bs16.asm b/uefi/linaro-edk2/DuetPkg/BootSector/bs16.asm
new file mode 100644
index 0000000..87b76db
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bs16.asm
@@ -0,0 +1,288 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    bs16.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE  EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT EQU     5

+BLOCK_SIZE                EQU     0200h

+BLOCK_MASK                EQU     01ffh

+BLOCK_SHIFT               EQU     9

+                                               ; "EFILDR_____"

+LOADER_FILENAME_PART1     EQU     04c494645h   ; "EFIL"

+LOADER_FILENAME_PART2     EQU     036315244h   ; "DR16"

+LOADER_FILENAME_PART3     EQU     020202036h   ; "6___"

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst                  - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+; BPB data below will be fixed by tool

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+Id                db  "    "        ; Id                  - 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT16   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+

+; ****************************************************************************

+; Start Print

+; ****************************************************************************

+  lea  si, cs:[StartString]

+  call PrintString

+

+; ****************************************************************************

+; Print over

+; ****************************************************************************

+

+  mov   ax,cs         ; ax = 0

+  mov   ss,ax         ; ss = 0

+  add   ax,1000h

+  mov   ds,ax

+

+  mov   sp,07c00h     ; sp = 0x7c00

+  mov   bp,sp         ; bp = 0x7c00

+

+  mov   ah,8                                ; ah = 8 - Get Drive Parameters Function

+  mov   byte ptr [bp+PhysicalDrive],dl      ; BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   13h                                 ; Get Drive Parameters

+  xor   ax,ax                   ; ax = 0

+  mov   al,dh                   ; al = dh

+  inc   al                      ; MaxHead = al + 1

+  push  ax                      ; 0000:7bfe = MaxHead

+  mov   al,cl                   ; al = cl

+  and   al,03fh                 ; MaxSector = al & 0x3f

+  push  ax                      ; 0000:7bfc = MaxSector

+

+  cmp   word ptr [bp+SectorSignature],0aa55h  ; Verify Boot Sector Signature

+  jne   BadBootSector

+  mov   cx,word ptr [bp+RootEntries]      ; cx = RootEntries

+  shl   cx,FAT_DIRECTORY_ENTRY_SHIFT      ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  and   bx,BLOCK_MASK                     ; See if it is an even number of sectors long

+  jne   BadBootSector                     ; If is isn't, then the boot sector is bad.

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  shr   bx,BLOCK_SHIFT                    ; bx = size of Root Directory in sectors

+  mov   al,byte ptr [bp+NoFats]           ; al = NoFats

+  xor   ah,ah                             ; ah = 0  ==> ax = NoFats

+  mul   word ptr [bp+SectorsPerFat]       ; ax = NoFats * SectorsPerFat

+  add   ax,word ptr [bp+ReservedSectors]  ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  push  ds

+  pop   es

+  xor   di,di                             ; Store directory in es:di = 1000:0000

+  call  ReadBlocks                        ; Read entire Root Directory

+  add   ax,bx                             ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA (FirstDataSector)

+  mov   word ptr [bp],ax                  ; Save FirstClusterLBA (FirstDataSector) for later use

+

+  ; dx - variable storage (initial value is 0)

+  ; bx - loader (initial value is 0)

+  xor   dx, dx

+  xor   bx, bx

+

+FindEFILDR:

+  cmp   dword ptr [di],LOADER_FILENAME_PART1         ; Compare to "EFIL"

+  jne   FindVARSTORE

+  cmp   dword ptr [di+4],LOADER_FILENAME_PART2

+  jne   FindVARSTORE

+  cmp   dword ptr [di+7],LOADER_FILENAME_PART3

+  jne   FindVARSTORE

+  mov   bx, word ptr [di+26]              ; bx = Start Cluster for EFILDR  <----------------------------------

+  test  dx, dx

+  je    FindNext                          ; Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE:

+  ; if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmp   dword ptr [di], 056494645h        ; Compare to "EFIV"

+  jne   FindNext

+  cmp   dword ptr [di+4], 020205241h      ; Compare to "AR  "

+  jne   FindNext

+  cmp   dword ptr [di+7], 04e494220h      ; Compare to " BIN"

+  jne   FindNext

+  mov   dx, di                            ; dx = Offset of Start Cluster for Efivar.bin <---------------------

+  add   dx, 26

+  test  bx, bx

+  je    FindNext                          ; Efildr is not loaded

+  jmp   FoundAll

+  

+FindNext:

+  ; go to next find

+  add   di,FAT_DIRECTORY_ENTRY_SIZE       ; Increment di

+  sub   cx,FAT_DIRECTORY_ENTRY_SIZE       ; Decrement cx

+  ; TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll:

+FoundEFILDR:

+  mov     cx,bx                               ; cx = Start Cluster for EFILDR  <----------------------------------

+  mov     ax,cs                               ; Destination = 2000:0000

+  add     ax,2000h

+  mov     es,ax

+  xor     di,di

+ReadFirstClusterOfEFILDR:

+  mov     ax,cx                               ; ax = StartCluster

+  sub     ax,2                                ; ax = StartCluster - 2

+  xor     bh,bh                               

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+  push    dx

+  mul     bx

+  pop     dx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+  add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xor     bh,bh

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = Number of Sectors in a cluster

+  push    es

+  call    ReadBlocks

+  pop     ax

+JumpIntoFirstSectorOfEFILDR:

+  mov     word ptr [bp+JumpSegment],ax

+JumpFarInstruction:

+  db      0eah

+JumpOffset:

+  dw      0000h

+JumpSegment:

+  dw      2000h

+

+

+PrintString:

+  mov  ax,0b800h

+  mov  es,ax

+  mov  ax, 07c0h

+  mov  ds, ax

+  mov  cx, 7

+  mov  di, 160

+  rep  movsw

+  ret

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+  pusha

+  add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+  add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+  mov     esi,eax                             ; esi = Start LBA

+  mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+  mov     bp,07bfch                           ; bp = 0x7bfc

+  mov     eax,esi                             ; eax = Start LBA

+  xor     edx,edx                             ; edx = 0

+  movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+  div     ebx                                 ; ax = StartLBA / MaxSector

+  inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+  sub     bx,dx                               ; bx = MaxSector - Sector

+  inc     bx                                  ; bx = MaxSector - Sector + 1

+  cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+  push    cx

+  mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+  xor     dx,dx                               ; dx = 0

+  div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                              ; dx = ax % (MaxHead + 1) = Head

+

+  push    bx                                  ; Save number of blocks to transfer

+  mov     dh,dl                               ; dh = Head

+  mov     bp,07c00h                           ; bp = 0x7c00

+  mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+  mov     ch,al                               ; ch = Cylinder

+  mov     al,bl                               ; al = Blocks

+  mov     ah,2                                ; ah = Function 2

+  mov     bx,di                               ; es:bx = Buffer address

+  int     013h

+  jc      DiskError

+  pop     bx

+  pop     cx

+  movzx   ebx,bx

+  add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+  sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+  mov     ax,es

+  shl     bx,(BLOCK_SHIFT-4)

+  add     ax,bx

+  mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmp     cx,0

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+; ****************************************************************************

+; ERROR Condition:

+; ****************************************************************************

+NotFoundAll:

+  ; if we found EFILDR, continue

+  test bx,bx

+  jne  FoundEFILDR

+BadBootSector:

+DiskError:

+  lea  si, cs:[ErrorString]

+  call PrintString

+Halt:

+  jmp   Halt

+

+StartString:

+  db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch, '!', 0ch

+ErrorString:

+  db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+; ****************************************************************************

+; LBA Offset for BootSector, need patched by tool for HD boot.

+; ****************************************************************************

+

+  org 01fah

+LBAOffsetForBootSector:

+  dd        0h

+

+; ****************************************************************************

+; Sector Signature

+; ****************************************************************************

+

+  org 01feh

+SectorSignature:

+  dw        0aa55h      ; Boot Sector Signature

+

+  end 

+  

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bs32.S b/uefi/linaro-edk2/DuetPkg/BootSector/bs32.S
new file mode 100644
index 0000000..2584517
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bs32.S
@@ -0,0 +1,312 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    bs32.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+        #.MODEL small

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                      FAT_DIRECTORY_ENTRY_SIZE, 0x0020

+.equ                      FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                      BLOCK_SIZE, 0x0200

+.equ                      BLOCK_MASK, 0x01ff

+.equ                      BLOCK_SHIFT, 9

+                                               # "EFILDR_____"

+.equ                      LOADER_FILENAME_PART1, 0x4c494645    # "EFIL"

+.equ                      LOADER_FILENAME_PART2, 0x30325244    # "DR20"

+.equ                      LOADER_FILENAME_PART3, 0x20202030    # "0___"

+

+        .org 0x0

+.global _start

+_start:

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst                  - 3 bytes

+  nop

+

+OemId:             .ascii  "INTEL   "   # OemId               - 8 bytes

+# BPB data below will be fixed by tool

+SectorSize:        .word  0             # Sector Size         - 16 bits

+SectorsPerCluster: .byte  0             # Sector Per Cluster  - 8 bits

+ReservedSectors:   .word  0             # Reserved Sectors    - 16 bits

+NoFats:            .byte  0             # Number of FATs      - 8 bits

+RootEntries:       .word  0             # Root Entries        - 16 bits

+Sectors:           .word  0             # Number of Sectors   - 16 bits

+Media:             .byte  0             # Media               - 8 bits  - ignored

+SectorsPerFat:     .word  0             # Sectors Per FAT     - 16 bits

+SectorsPerTrack:   .word  0             # Sectors Per Track   - 16 bits - ignored

+Heads:             .word  0             # Heads               - 16 bits - ignored

+HiddenSectors:     .long  0             # Hidden Sectors      - 32 bits - ignored

+LargeSectors:      .long  0             # Large Sectors       - 32 bits 

+

+#******************************************************************************

+#

+#The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+#the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+#

+#******************************************************************************

+

+SectorsPerFat32:   .long  0              # Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags:          .word  0              # Mirror Flag                     - 2 bytes

+FSVersion:         .word  0              # File System Version             - 2 bytes

+RootCluster:       .long  0              # 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo:            .word  0              # Sector Number of FSINFO         - 2 bytes

+BkBootSector:      .word  0              # Sector Number of Bk BootSector  - 2 bytes

+Reserved:          .fill  12, 1, 0       # Reserved Field                  - 12 bytes

+PhysicalDrive:     .byte  0              # Physical Drive Number           - 1 byte

+Reserved1:         .byte  0              # Reserved Field                  - 1 byte

+Signature:         .byte  0              # Extended Boot Signature         - 1 byte

+VolId:             .ascii  "    "        # Volume Serial Number            - 4 bytes

+FatLabel:          .ascii  "           " # Volume Label                    - 11 bytes

+FileSystemType:    .ascii  "FAT32   "    # File System Type                - 8 bytes

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+

+# ****************************************************************************

+# Start Print

+# ****************************************************************************

+  movw $StartString, %si

+  call PrintString

+

+# ****************************************************************************

+# Print over

+# ****************************************************************************

+

+  movw  %cs, %ax      # ax = 0

+  movw  %ax, %ss      # ss = 0

+  addw  $0x1000, %ax

+  movw  %ax, %ds

+

+  movw  $0x7c00, %sp  # sp = 0x7c00

+  movw  %sp, %bp      # bp = 0x7c00

+

+  movb  $8, %ah                             # ah = 8 - Get Drive Parameters Function

+  movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   $0x13                               # Get Drive Parameters

+  xorw  %ax, %ax                # ax = 0

+  movb  %dh, %al                # al = dh

+  incb  %al                     # MaxHead = al + 1

+  pushw %ax                     # 0000:7bfe = MaxHead

+  movb  %cl, %al                # al = cl

+  andb  $0x3f, %al              # MaxSector = al & 0x3f

+  pushw %ax                     # 0000:7bfc = MaxSector

+

+  cmpw  $0xaa55, SectorSignature(%bp)         # Verify Boot Sector Signature

+  jne   BadBootSector

+  movw  RootEntries(%bp), %cx             # cx = RootEntries

+  shlw  $FAT_DIRECTORY_ENTRY_SHIFT, %cx   # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  andw  $BLOCK_MASK, %bx                  # See if it is an even number of sectors long

+  jne   BadBootSector                     # If is isn't, then the boot sector is bad.

+  movw  %cx, %bx                          # bx = size of the Root Directory in bytes

+  shrw  $BLOCK_SHIFT, %bx                 # bx = size of Root Directory in sectors

+  movb  NoFats(%bp), %al                  # al = NoFats

+  xorb  %ah, %ah                          # ah = 0  ==> ax = NoFats

+  mulw  SectorsPerFat32(%bp)              # ax = NoFats * SectorsPerFat

+  addw  ReservedSectors(%bp), %ax         # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  addw  %bx, %ax                          # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA

+  movw  %ax, (%bp)                        # Save FirstClusterLBA for later use

+

+  movw  RootCluster(%bp), %ax             # ax = StartCluster of Root Directory

+  subw  $2, %ax                           # ax = StartCluster - 2

+  xorb  %bh, %bh

+  movb  SectorsPerCluster(%bp), %bl       # bx = SectorsPerCluster

+  mulw  %bx                               # ax = (StartCluster - 2) * SectorsPerCluster

+  addw  (%bp), %ax                        # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  pushw %ds

+  popw  %es

+  xorw  %di, %di                          # Store directory in es:di = 1000:0000

+  call  ReadBlocks                        # Read StartCluster of Root Directory

+

+  # dx - variable storage (initial value is 0)

+  # bx - loader (initial value is 0)

+  xorw  %dx, %dx

+  xorw  %bx, %bx

+

+FindEFILDR: 

+  cmpl  $LOADER_FILENAME_PART1, (%di)

+  jne   FindVARSTORE

+  cmpl  $LOADER_FILENAME_PART2, 4(%di)

+  jne   FindVARSTORE

+  cmpl  $LOADER_FILENAME_PART3, 7(%di)

+  jne   FindVARSTORE

+  movw  26(%di), %bx                      # bx = Start Cluster for EFILDR  <----------------------------------

+  testw %dx, %dx

+  je    FindNext                          # Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE: 

+  ## if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmpl  $0x56494645, (%di)                # Compare to "EFIV"

+  jne   FindNext

+  cmpl  $0x20205241, 4(%di)               # Compare to "AR  "

+  jne   FindNext

+  cmpl  $0x4e494220, 7(%di)               # Compare to " BIN"

+  jne   FindNext

+  movw  %di, %dx                          # dx = Offset of Start Cluster for Efivar.bin <---------------------

+  addw  $26, %dx

+  testw %bx, %bx

+  je    FindNext                          # Efildr is not loaded

+  jmp   FoundAll

+

+FindNext: 

+  # go to next find

+  addw  $FAT_DIRECTORY_ENTRY_SIZE, %di    # Increment di

+  subw  $FAT_DIRECTORY_ENTRY_SIZE, %cx    # Decrement cx

+  # TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll: 

+FoundEFILDR: 

+  movw    %bx, %cx                            # cx = Start Cluster for EFILDR  <----------------------------------

+  movw    %cs, %ax                            # Destination = 2000:0000

+  addw    $0x2000, %ax

+  movw    %ax, %es

+  xorw    %di, %di

+ReadFirstClusterOfEFILDR: 

+  movw    %cx, %ax                            # ax = StartCluster

+  subw    $2, %ax                             # ax = StartCluster - 2

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+  pushw   %dx

+  mulw    %bx

+  popw    %dx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+  addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xorb    %bh, %bh

+  movb    SectorsPerCluster(%bp), %bl         # bx = Number of Sectors in a cluster

+  pushw   %es

+  call    ReadBlocks

+  popw    %ax

+JumpIntoFirstSectorOfEFILDR: 

+  movw    %ax, JumpSegment(%bp)

+JumpFarInstruction: 

+  .byte   0xea

+JumpOffset: 

+  .word   0x000

+JumpSegment: 

+  .word   0x2000

+

+

+PrintString: 

+  movw $0xb800, %ax

+  movw %ax, %es

+  movw $0x7c0, %ax

+  movw %ax, %ds

+  movw $6, %cx

+  movw $160, %di

+  rep

+  movsw

+  ret

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+  pusha

+  addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA

+  addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+  movl    %eax, %esi                          # esi = Start LBA

+  movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+  movw    $0x7bfc, %bp                        # bp = 0x7bfc

+  movl    %esi, %eax                          # eax = Start LBA

+  xorl    %edx, %edx                          # edx = 0

+  movzwl  (%bp), %ebx                         # bx = MaxSector

+  divl    %ebx                                # ax = StartLBA / MaxSector

+  incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+  subw    %dx, %bx                            # bx = MaxSector - Sector

+  incw    %bx                                 # bx = MaxSector - Sector + 1

+  cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+  pushw   %cx

+  movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+  xorw    %dx, %dx                            # dx = 0

+  divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                              # dx = ax % (MaxHead + 1) = Head

+

+  pushw   %bx                                 # Save number of blocks to transfer

+  movb    %dl, %dh                            # dh = Head

+  movw    $0x7c00, %bp                        # bp = 0x7c00

+  movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+  movb    %al, %ch                            # ch = Cylinder

+  movb    %bl, %al                            # al = Blocks

+  movb    $2, %ah                             # ah = Function 2

+  movw    %di, %bx                            # es:bx = Buffer address

+  int     $0x13

+  jc      DiskError

+  popw    %bx

+  popw    %cx

+  movzwl  %bx, %ebx

+  addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+  subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+  movw    %es, %ax

+  shlw    $(BLOCK_SHIFT-4), %bx

+  addw    %bx, %ax

+  movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmpw    $0, %cx

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+# ****************************************************************************

+# ERROR Condition:

+# ****************************************************************************

+NotFoundAll: 

+  ## if we found EFILDR, continue

+  testw %bx, %bx

+  jne  FoundEFILDR

+BadBootSector: 

+DiskError: 

+  movw $ErrorString, %si

+  call PrintString

+Halt: 

+  jmp   Halt

+

+StartString: 

+  .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c

+ErrorString: 

+  .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c

+

+# ****************************************************************************

+# LBA Offset for BootSector, need patched by tool for HD boot.

+# ****************************************************************************

+

+  .org 0x01fa

+LBAOffsetForBootSector: 

+  .long     0x0

+

+# ****************************************************************************

+# Sector Signature

+# ****************************************************************************

+

+  .org 0x01fe

+SectorSignature: 

+  .word     0xaa55      # Boot Sector Signature

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/bs32.asm b/uefi/linaro-edk2/DuetPkg/BootSector/bs32.asm
new file mode 100644
index 0000000..7105ae6
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/bs32.asm
@@ -0,0 +1,310 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    bs32.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE  EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT EQU     5

+BLOCK_SIZE                EQU     0200h

+BLOCK_MASK                EQU     01ffh

+BLOCK_SHIFT               EQU     9

+                                               ; "EFILDR_____"

+LOADER_FILENAME_PART1     EQU     04c494645h   ; "EFIL"

+LOADER_FILENAME_PART2     EQU     030325244h   ; "DR20"

+LOADER_FILENAME_PART3     EQU     020202030h   ; "0___"

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst                  - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+; BPB data below will be fixed by tool

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+

+;******************************************************************************

+;

+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+;

+;******************************************************************************

+

+SectorsPerFat32   dd  0             ; Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags          dw  0             ; Mirror Flag                     - 2 bytes

+FSVersion         dw  0             ; File System Version             - 2 bytes

+RootCluster       dd  0             ; 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo            dw  0             ; Sector Number of FSINFO         - 2 bytes

+BkBootSector      dw  0             ; Sector Number of Bk BootSector  - 2 bytes

+Reserved          db  12 dup(0)     ; Reserved Field                  - 12 bytes

+PhysicalDrive     db  0             ; Physical Drive Number           - 1 byte

+Reserved1         db  0             ; Reserved Field                  - 1 byte

+Signature         db  0             ; Extended Boot Signature         - 1 byte

+VolId             db  "    "        ; Volume Serial Number            - 4 bytes

+FatLabel          db  "           " ; Volume Label                    - 11 bytes

+FileSystemType    db  "FAT32   "    ; File System Type                - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+

+; ****************************************************************************

+; Start Print

+; ****************************************************************************

+  mov  si, offset StartString

+  call PrintString

+

+; ****************************************************************************

+; Print over

+; ****************************************************************************

+

+  mov   ax,cs         ; ax = 0

+  mov   ss,ax         ; ss = 0

+  add   ax,1000h

+  mov   ds,ax

+

+  mov   sp,07c00h     ; sp = 0x7c00

+  mov   bp,sp         ; bp = 0x7c00

+

+  mov   ah,8                                ; ah = 8 - Get Drive Parameters Function

+  mov   byte ptr [bp+PhysicalDrive],dl      ; BBS defines that BIOS would pass the booting driver number to the loader through DL

+  int   13h                                 ; Get Drive Parameters

+  xor   ax,ax                   ; ax = 0

+  mov   al,dh                   ; al = dh

+  inc   al                      ; MaxHead = al + 1

+  push  ax                      ; 0000:7bfe = MaxHead

+  mov   al,cl                   ; al = cl

+  and   al,03fh                 ; MaxSector = al & 0x3f

+  push  ax                      ; 0000:7bfc = MaxSector

+

+  cmp   word ptr [bp+SectorSignature],0aa55h  ; Verify Boot Sector Signature

+  jne   BadBootSector

+  mov   cx,word ptr [bp+RootEntries]      ; cx = RootEntries

+  shl   cx,FAT_DIRECTORY_ENTRY_SHIFT      ; cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  and   bx,BLOCK_MASK                     ; See if it is an even number of sectors long

+  jne   BadBootSector                     ; If is isn't, then the boot sector is bad.

+  mov   bx,cx                             ; bx = size of the Root Directory in bytes

+  shr   bx,BLOCK_SHIFT                    ; bx = size of Root Directory in sectors

+  mov   al,byte ptr [bp+NoFats]           ; al = NoFats

+  xor   ah,ah                             ; ah = 0  ==> ax = NoFats

+  mul   word ptr [bp+SectorsPerFat32]     ; ax = NoFats * SectorsPerFat

+  add   ax,word ptr [bp+ReservedSectors]  ; ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA

+  add   ax,bx                             ; ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA

+  mov   word ptr [bp],ax                  ; Save FirstClusterLBA for later use

+  

+  mov   ax,word ptr [bp+RootCluster]      ; ax = StartCluster of Root Directory

+  sub   ax,2                              ; ax = StartCluster - 2

+  xor   bh,bh                               

+  mov   bl,byte ptr [bp+SectorsPerCluster]; bx = SectorsPerCluster

+  mul   bx                                ; ax = (StartCluster - 2) * SectorsPerCluster

+  add   ax, word ptr [bp]                 ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  push  ds

+  pop   es

+  xor   di,di                             ; Store directory in es:di = 1000:0000

+  call  ReadBlocks                        ; Read StartCluster of Root Directory

+

+  ; dx - variable storage (initial value is 0)

+  ; bx - loader (initial value is 0)

+  xor   dx, dx

+  xor   bx, bx

+

+FindEFILDR:

+  cmp   dword ptr [di],LOADER_FILENAME_PART1         ; Compare to "EFIL"

+  jne   FindVARSTORE

+  cmp   dword ptr [di+4],LOADER_FILENAME_PART2

+  jne   FindVARSTORE

+  cmp   dword ptr [di+7],LOADER_FILENAME_PART3

+  jne   FindVARSTORE

+  mov   bx, word ptr [di+26]              ; bx = Start Cluster for EFILDR  <----------------------------------

+  test  dx, dx

+  je    FindNext                          ; Efivar.bin is not loaded

+  jmp   FoundAll

+

+FindVARSTORE:

+  ; if the file is not loader file, see if it's "EFIVAR  BIN"

+  cmp   dword ptr [di], 056494645h        ; Compare to "EFIV"

+  jne   FindNext

+  cmp   dword ptr [di+4], 020205241h      ; Compare to "AR  "

+  jne   FindNext

+  cmp   dword ptr [di+7], 04e494220h      ; Compare to " BIN"

+  jne   FindNext

+  mov   dx, di                            ; dx = Offset of Start Cluster for Efivar.bin <---------------------

+  add   dx, 26

+  test  bx, bx

+  je    FindNext                          ; Efildr is not loaded

+  jmp   FoundAll

+  

+FindNext:

+  ; go to next find

+  add   di,FAT_DIRECTORY_ENTRY_SIZE       ; Increment di

+  sub   cx,FAT_DIRECTORY_ENTRY_SIZE       ; Decrement cx

+  ; TODO: jump to FindVarStore if ...

+  jne   FindEFILDR

+  jmp   NotFoundAll

+

+FoundAll:

+FoundEFILDR:

+  mov     cx,bx                               ; cx = Start Cluster for EFILDR  <----------------------------------

+  mov     ax,cs                               ; Destination = 2000:0000

+  add     ax,2000h

+  mov     es,ax

+  xor     di,di

+ReadFirstClusterOfEFILDR:

+  mov     ax,cx                               ; ax = StartCluster

+  sub     ax,2                                ; ax = StartCluster - 2

+  xor     bh,bh                               

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+  push    dx

+  mul     bx

+  pop     dx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+  add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+  xor     bh,bh

+  mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = Number of Sectors in a cluster

+  push    es

+  call    ReadBlocks

+  pop     ax

+JumpIntoFirstSectorOfEFILDR:

+  mov     word ptr [bp+JumpSegment],ax

+JumpFarInstruction:

+  db      0eah

+JumpOffset:

+  dw      0000h

+JumpSegment:

+  dw      2000h

+

+

+PrintString:

+  mov  ax,0b800h

+  mov  es,ax

+  mov  ax, 07c0h

+  mov  ds, ax

+  mov  cx, 6

+  mov  di, 160

+  rep  movsw

+  ret

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+  pusha

+  add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+  add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+  mov     esi,eax                             ; esi = Start LBA

+  mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+  mov     bp,07bfch                           ; bp = 0x7bfc

+  mov     eax,esi                             ; eax = Start LBA

+  xor     edx,edx                             ; edx = 0

+  movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+  div     ebx                                 ; ax = StartLBA / MaxSector

+  inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+  sub     bx,dx                               ; bx = MaxSector - Sector

+  inc     bx                                  ; bx = MaxSector - Sector + 1

+  cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+  jg      LimitTransfer

+  mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+  push    cx

+  mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+  xor     dx,dx                               ; dx = 0

+  div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                              ; dx = ax % (MaxHead + 1) = Head

+

+  push    bx                                  ; Save number of blocks to transfer

+  mov     dh,dl                               ; dh = Head

+  mov     bp,07c00h                           ; bp = 0x7c00

+  mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+  mov     ch,al                               ; ch = Cylinder

+  mov     al,bl                               ; al = Blocks

+  mov     ah,2                                ; ah = Function 2

+  mov     bx,di                               ; es:bx = Buffer address

+  int     013h

+  jc      DiskError

+  pop     bx

+  pop     cx

+  movzx   ebx,bx

+  add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+  sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+  mov     ax,es

+  shl     bx,(BLOCK_SHIFT-4)

+  add     ax,bx

+  mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+  cmp     cx,0

+  jne     ReadCylinderLoop

+  popa

+  ret

+

+; ****************************************************************************

+; ERROR Condition:

+; ****************************************************************************

+NotFoundAll:

+  ; if we found EFILDR, continue

+  test bx,bx

+  jne  FoundEFILDR

+BadBootSector:

+DiskError:

+  mov  si, offset ErrorString

+  call PrintString

+Halt:

+  jmp   Halt

+

+StartString:

+  db 'B', 0ch, 'S', 0ch, 't', 0ch, 'a', 0ch, 'r', 0ch, 't', 0ch

+ErrorString:

+  db 'B', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch

+

+; ****************************************************************************

+; LBA Offset for BootSector, need patched by tool for HD boot.

+; ****************************************************************************

+

+  org 01fah

+LBAOffsetForBootSector:

+  dd        0h

+

+; ****************************************************************************

+; Sector Signature

+; ****************************************************************************

+

+  org 01feh

+SectorSignature:

+  dw        0aa55h      ; Boot Sector Signature

+

+  end 

+  

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/efi32.S b/uefi/linaro-edk2/DuetPkg/BootSector/efi32.S
new file mode 100644
index 0000000..ebbc450
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/efi32.S
@@ -0,0 +1,1176 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    efi32.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+##############################################################################

+# Now in 32-bit protected mode.

+##############################################################################

+

+        .org 0x21000

+

+.global _start

+_start:

+

+.equ                 DEFAULT_HANDLER_SIZE, INT1 - INT0

+

+.macro jmpCommonIdtEntry  

+    # jmp     commonIdtEntry - this must be hand coded to keep the assembler from

+    #                          using a 8 bit reletive jump when the entries are

+    #                          within 255 bytes of the common entry.  This must

+    #                          be done to maintain the consistency of the size

+    #                          of entry points...

+    .byte   0xe9                        # jmp 16 bit relative

+    .long      commonIdtEntry - . - 4   # offset to jump to     

+.endm

+

+Start:  

+    movw    %bx, %ax

+    movw    %ax, %ds

+    movw    %ax, %es

+    movw    %ax, %fs

+    movw    %ax, %gs

+    movw    %ax, %ss

+    movl    $0x001ffff0, %esp

+

+    call    ClearScreen

+

+    # Populate IDT with meaningful offsets for exception handlers...

+    sidt    Idtr            

+

+    movl    Halt, %eax

+    movl    %eax, %ebx                  # use bx to copy 15..0 to descriptors

+    shrl    $16, %eax                   # use ax to copy 31..16 to descriptors 

+    movl    $0x78, %ecx                 # 78h IDT entries to initialize with unique entry points (exceptions)

+    movl    (Idtr + 2), %esi

+    movl    (%esi), %edi

+

+LOOP_1:                                         # loop through all IDT entries exception handlers and initialize to default handler

+    movw    %bx, (%edi)                         # write bits 15..0 of offset

+    movw    $0x20, 2(%edi)                      # SYS_CODE_SEL from GDT

+    movw    $(0x0e00 | 0x8000), 4(%edi)         # type = 386 interrupt gate, present

+    movw    %ax, 6(%edi)                        # write bits 31..16 of offset

+    addl    $8, %edi                            # move up to next descriptor

+    addw    DEFAULT_HANDLER_SIZE, %bx           # move to next entry point

+    loopl   LOOP_1                                 # loop back through again until all descriptors are initialized

+

+    ## at this point edi contains the offset of the descriptor for INT 20

+    ## and bx contains the low 16 bits of the offset of the default handler

+    ## so initialize all the rest of the descriptors with these two values...

+#    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)

+#@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+#    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+#    mov     word ptr [edi+2], 20h               ; SYS_CODE_SEL from GDT

+#    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+#    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+#    add     edi, 8                              ; move up to next descriptor

+#    loop    @b                                  ; loop back through again until all descriptors are initialized

+

+

+##  DUMP    location of IDT and several of the descriptors

+#    mov     ecx, 8

+#    mov     eax, [offset Idtr + 2]

+#    mov     eax, [eax]

+#    mov     edi, 0b8000h

+#    call    PrintDword

+#    mov     esi, eax

+#    mov     edi, 0b80a0h

+#    jmp     OuterLoop

+

+##    

+## just for fun, let's do a software interrupt to see if we correctly land in the exception handler...

+#    mov     eax, 011111111h

+#    mov     ebx, 022222222h

+#    mov     ecx, 033333333h

+#    mov     edx, 044444444h

+#    mov     ebp, 055555555h

+#    mov     esi, 066666666h

+#    mov     edi, 077777777h

+#    push    011111111h

+#    push    022222222h

+#    push    033333333h

+#    int     119

+

+

+    movl    $0x22000, %esi              # esi = 22000

+    movl    0x14(%esi), %eax            # eax = [22014]

+    addl    %eax, %esi                  # esi = 22000 + [22014] = Base of EFILDR.C

+    movl    0x3c(%esi), %ebp            # ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C

+    addl    %esi, %ebp

+    movl    0x34(%ebp), %edi            # edi = [[22000 + [22014] + 3c] + 30] = ImageBase

+    movl    0x28(%ebp), %eax            # eax = [[22000 + [22014] + 3c] + 24] = EntryPoint

+    addl    %edi, %eax                  # eax = ImageBase + EntryPoint

+    movl    %eax, EfiLdrOffset             # Modify far jump instruction for correct entry point

+

+    movw    6(%ebp), %bx                # bx = Number of sections

+    xorl    %eax, %eax

+    movw    0x14(%ebp), %ax             # ax = Optional Header Size

+    addl    %eax, %ebp

+    addl    $0x18, %ebp                 # ebp = Start of 1st Section

+

+SectionLoop: 

+    pushl   %esi                        # Save Base of EFILDR.C

+    pushl   %edi                        # Save ImageBase

+    addl    0x14(%ebp), %esi            # esi = Base of EFILDR.C + PointerToRawData

+    addl    0x0c(%ebp), %edi            # edi = ImageBase + VirtualAddress

+    movl    0x10(%ebp), %ecx            # ecs = SizeOfRawData

+

+    cld

+    shrl    $2, %ecx

+    rep

+    movsl

+

+    popl    %edi                        # Restore ImageBase

+    popl    %esi                        # Restore Base of EFILDR.C

+

+    addw    $0x28, %bp                  # ebp = ebp + 028h = Pointer to next section record

+    decw    %bx

+    cmpw    $0, %bx

+    jne     SectionLoop

+

+    movzwl  (Idtr), %eax                # get size of IDT

+    incl    %eax

+    addl    (Idtr + 2), %eax            # add to base of IDT to get location of memory map... 

+    pushl   %eax                        # push memory map location on stack for call to EFILDR...

+

+    pushl   %eax                        # push return address (useless, just for stack balance)

+    .byte   0xb8

+EfiLdrOffset: 

+    .long   0x00401000                  # Offset of EFILDR

+# mov eax, 401000h

+    pushl   %eax

+    ret

+

+#    db      "**** DEFAULT IDT ENTRY ***",0

+    .p2align 1

+Halt: 

+INT0: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x0

+    jmpCommonIdtEntry 

+#    db      0e9h                        ; jmp 16 bit reletive 

+#    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+

+INT1: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x1

+    jmpCommonIdtEntry 

+

+INT2: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x2

+    jmpCommonIdtEntry 

+

+INT3: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x3

+    jmpCommonIdtEntry 

+

+INT4: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x4

+    jmpCommonIdtEntry 

+

+INT5: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x5

+    jmpCommonIdtEntry 

+

+INT6: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x6

+    jmpCommonIdtEntry 

+

+INT7: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x7

+    jmpCommonIdtEntry 

+

+INT8: 

+#   Double fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $0x8

+    jmpCommonIdtEntry 

+

+INT9: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x9

+    jmpCommonIdtEntry 

+

+INT10: 

+#   Invalid TSS causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $10

+    jmpCommonIdtEntry 

+

+INT11: 

+#   Segment Not Present causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $11

+    jmpCommonIdtEntry 

+

+INT12: 

+#   Stack fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $12

+    jmpCommonIdtEntry 

+

+INT13: 

+#   GP fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $13

+    jmpCommonIdtEntry 

+

+INT14: 

+#   Page fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $14

+    jmpCommonIdtEntry 

+

+INT15: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $15

+    jmpCommonIdtEntry 

+

+INT16: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $16

+    jmpCommonIdtEntry 

+

+INT17: 

+#   Alignment check causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $17

+    jmpCommonIdtEntry 

+

+INT18: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $18

+    jmpCommonIdtEntry 

+

+INT19: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $19

+    jmpCommonIdtEntry 

+

+INTUnknown: 

+# The following segment repeats (0x78 - 20) times:

+# No. 1

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 2

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 3

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 4

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 5

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 6

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 7

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 8

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 9

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 10

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 11

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 12

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 13

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 14

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 15

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 16

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 17

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 18

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 19

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 20

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 21

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 22

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 23

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 24

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 25

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 26

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 27

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 28

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 29

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 30

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 31

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 32

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 33

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 34

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 35

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 36

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 37

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 38

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 39

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 40

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 41

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 42

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 43

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 44

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 45

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 46

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 47

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 48

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 49

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 50

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 51

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 52

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 53

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 54

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 55

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 56

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 57

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 58

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 59

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 60

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 61

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 62

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 63

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 64

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 65

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 66

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 67

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 68

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 69

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 70

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 71

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 72

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 73

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 74

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 75

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 76

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 77

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 78

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 79

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 80

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 81

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 82

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 83

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 84

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 85

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 86

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 87

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 88

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 89

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 90

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 91

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 92

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 93

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 94

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 95

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 96

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 97

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 98

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 99

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+# No. 100

+    pushl   $0x0    # push error code place holder on the stack

+#   push    $0xxx   # push vector number

+    .byte   0x6a

+    .long   ( . - INTUnknown - 3 ) / 9 + 20  # vector number

+    jmpCommonIdtEntry 

+

+

+commonIdtEntry: 

+    pushal

+    movl    %esp, %ebp

+##

+##  At this point the stack looks like this:

+##

+##      eflags

+##      Calling CS

+##      Calling EIP

+##      Error code or 0

+##      Int num or 0ffh for unknown int num

+##      eax

+##      ecx

+##      edx

+##      ebx

+##      esp

+##      ebp

+##      esi

+##      edi <------- ESP, EBP

+##      

+

+    call    ClearScreen

+    movl    String1, %esi

+    call    PrintString

+    movl    32(%ebp), %eax      ## move Int number into EAX 

+    cmpl    $19, %eax

+    ja      PrintDefaultString

+PrintExceptionString: 

+    shll    $2, %eax            ## multiply by 4 to get offset from StringTable to actual string address

+    addl    StringTable, %eax

+    movl    (%eax), %esi

+    jmp     PrintTheString

+PrintDefaultString: 

+    movl    IntUnknownString, %esi

+    # patch Int number

+    movl    %eax, %edx

+    call    A2C

+    movb    %al, 1(%esi)

+    movl    %edx, %eax

+    shrl    $4, %eax

+    call    A2C

+    movb    %al, (%esi)

+PrintTheString:        

+    call    PrintString

+    movl    String2, %esi

+    call    PrintString

+    movl    44(%ebp), %eax         # CS

+    call    PrintDword

+    movb    ':', %al

+    movb    %al, (%edi)

+    addl    $2, %edi

+    movl    40(%ebp), %eax         # EIP

+    call    PrintDword

+    movl    String3, %esi

+    call    PrintString

+

+    movl    $0xb8140, %edi

+

+    movl    StringEax, %esi           # eax

+    call    PrintString

+    movl    28(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEbx, %esi           # ebx

+    call    PrintString

+    movl    16(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEcx, %esi           # ecx

+    call    PrintString

+    movl    24(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEdx, %esi           # edx

+    call    PrintString

+    movl    20(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEcode, %esi         # error code

+    call    PrintString

+    movl    36(%ebp), %eax

+    call    PrintDword

+

+    movl    $0xb81e0, %edi

+

+    movl    StringEsp, %esi           # esp

+    call    PrintString

+    movl    12(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEbp, %esi           # ebp

+    call    PrintString

+    movl    8(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEsi, %esi           # esi

+    call    PrintString

+    movl    4(%ebp), %eax

+    call    PrintDword

+

+    movl    StringEdi, %esi          # edi

+    call    PrintString

+    movl    (%ebp), %eax

+    call    PrintDword

+

+    movl    StringEflags, %esi       # eflags

+    call    PrintString

+    movl    48(%ebp), %eax

+    call    PrintDword

+

+    movl    $0xb8320, %edi

+

+    movl    %ebp, %esi

+    addl    $52, %esi

+    movl    $8, %ecx

+

+

+OuterLoop: 

+    pushl   %ecx

+    movl    $8, %ecx

+    movl    %edi, %edx

+

+InnerLoop: 

+    movl    (%esi), %eax

+    call    PrintDword

+    addl    $4, %esi

+    movb    ' ', %al 

+    movb    %al, (%edi)

+    addl    $2, %edi

+    loop    InnerLoop

+

+    popl    %ecx

+    addl    $0xa0, %edx

+    movl    %edx, %edi

+    loop    OuterLoop

+

+

+    movl    $0xb8960, %edi

+

+    movl    40(%ebp), %eax # EIP

+    subl    $32*4, %eax

+    movl    %eax, %esi      # esi = eip - 32 DWORD linear (total 64 DWORD)

+

+    movl    $8, %ecx

+

+OuterLoop1: 

+    pushl   %ecx

+    movl    $8, %ecx

+    movl    %edi, %edx

+

+InnerLoop1: 

+    movl    (%esi), %eax

+    call    PrintDword

+    addl    $4, %esi

+    movb    ' ', %al 

+    movb    %al, (%edi)

+    addl    $2, %edi

+    loop    InnerLoop1

+

+    popl    %ecx

+    addl    $0xa0, %edx

+    movl    %edx, %edi

+    loop    OuterLoop1

+

+

+

+#    wbinvd ; this intruction does not support in early than 486 arch

+LN_C1:    

+    jmp     LN_C1

+#

+# return

+#

+    movl    %ebp, %esp

+    popal

+    addl    $8, %esp # error code and INT number

+

+    iretl

+

+

+PrintString: 

+    pushl   %eax

+LN_C2: 

+    movb    (%esi), %al

+    cmpb    $0, %al

+    je      LN_C3

+    movb    %al, (%edi)

+    incl    %esi

+    addl    $2, %edi

+    jmp     LN_C2

+LN_C3: 

+    popl    %eax

+    ret

+

+## EAX contains dword to print

+## EDI contains memory location (screen location) to print it to

+PrintDword: 

+    pushl   %ecx

+    pushl   %ebx

+    pushl   %eax

+

+    movl    $8, %ecx

+looptop: 

+    roll    $4, %eax

+    movb    %al, %bl

+    andb    $0xf, %bl

+    addb    '0', %bl

+    cmpb    '9', %bl

+    jle     LN_C4

+    addb    $7, %bl

+LN_C4: 

+    movb    %bl, (%edi)

+    addl    $2, %edi

+    loop    looptop

+    #wbinvd

+

+    popl    %eax

+    popl    %ebx

+    popl    %ecx

+    ret

+

+ClearScreen: 

+    pushl   %eax

+    pushl   %ecx

+

+    movb    $0x00, %al

+    movb    $0xc, %ah

+    movl    $0xb8000, %edi

+    movl    $80*24, %ecx

+LN_C5: 

+    movw    %ax, (%edi)

+    addl    $2, %edi

+    loop    LN_C5

+    movl    $0xb8000, %edi

+

+    popl    %ecx

+    popl    %eax

+

+    ret

+

+A2C: 

+    andb    $0xf, %al

+    addb    '0', %al

+    cmpb    '9', %al

+    jle     LN_C6

+    addb    $7, %al

+LN_C6: 

+    ret

+

+String1:            .asciz      "*** INT "

+

+Int0String:         .asciz      "00h Divide by 0 -"

+Int1String:         .asciz      "01h Debug exception -"

+Int2String:         .asciz      "02h NMI -"

+Int3String:         .asciz      "03h Breakpoint -"

+Int4String:         .asciz      "04h Overflow -"

+Int5String:         .asciz      "05h Bound -"

+Int6String:         .asciz      "06h Invalid opcode -"

+Int7String:         .asciz      "07h Device not available -"

+Int8String:         .asciz      "08h Double fault -"

+Int9String:         .asciz      "09h Coprocessor seg overrun (reserved) -"

+Int10String:        .asciz      "0Ah Invalid TSS -"

+Int11String:        .asciz      "0Bh Segment not present -"

+Int12String:        .asciz      "0Ch Stack fault -"

+Int13String:        .asciz      "0Dh General protection fault -"

+Int14String:        .asciz      "0Eh Page fault -"

+Int15String:        .asciz      "0Fh (Intel reserved) -"

+Int16String:        .asciz      "10h Floating point error -"

+Int17String:        .asciz      "11h Alignment check -"

+Int18String:        .asciz      "12h Machine check -"

+Int19String:        .asciz      "13h SIMD Floating-Point Exception -"

+IntUnknownString:   .asciz      "??h Unknown interrupt -"

+

+StringTable:   .long  Int0String, Int1String, Int2String, Int3String,    \

+                      Int4String, Int5String, Int6String, Int7String,    \

+                      Int8String, Int9String, Int10String, Int11String,  \

+                      Int12String, Int13String, Int14String, Int15String,\

+                      Int16String, Int17String, Int18String, Int19String

+

+String2:         .asciz  " HALT!! *** ("

+String3:         .asciz  ")"

+StringEax:       .asciz  "EAX="

+StringEbx:       .asciz  "EBX="

+StringEcx:       .asciz  "ECX="

+StringEdx:       .asciz  "EDX="

+StringEcode:     .asciz  "ECODE="

+StringEsp:       .asciz  "ESP="

+StringEbp:       .asciz  "EBP="

+StringEsi:       .asciz  "ESI="

+StringEdi:       .asciz  "EDI="

+StringEflags:    .asciz  "EFLAGS="

+

+Idtr:        .float  0

+

+    .org 0x21ffe

+BlockSignature: 

+    .word   0xaa55

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/efi32.asm b/uefi/linaro-edk2/DuetPkg/BootSector/efi32.asm
new file mode 100644
index 0000000..7ccf86f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/efi32.asm
@@ -0,0 +1,582 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    efi32.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; Now in 32-bit protected mode.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        .486

+        .model  flat        

+        .stack

+        .code

+        org 21000h

+        

+DEFAULT_HANDLER_SIZE EQU INT1 - INT0

+

+JmpCommonIdtEntry  macro

+    ; jmp     commonIdtEntry - this must be hand coded to keep the assembler from

+    ;                          using a 8 bit reletive jump when the entries are

+    ;                          within 255 bytes of the common entry.  This must

+    ;                          be done to maintain the consistency of the size

+    ;                          of entry points...

+    db      0e9h                        ; jmp 16 bit relative 

+    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+endm    

+

+        

+Start:  

+    mov     ax,bx                      ; flat data descriptor in BX

+    mov     ds,ax

+    mov     es,ax

+    mov     fs,ax

+    mov     gs,ax

+    mov     ss,ax

+    mov     esp,0001ffff0h

+

+    call    ClearScreen

+

+    ; Populate IDT with meaningful offsets for exception handlers...

+    sidt    fword ptr [Idtr]             ; get fword address of IDT

+

+    mov     eax, offset Halt

+    mov     ebx, eax                    ; use bx to copy 15..0 to descriptors

+    shr     eax, 16                     ; use ax to copy 31..16 to descriptors 

+    mov     ecx, 78h                    ; 78h IDT entries to initialize with unique entry points (exceptions)

+    mov     esi, [offset Idtr + 2]

+    mov     edi, [esi]

+    

+@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+    mov     word ptr [edi+2], 20h               ; SYS_CODE_SEL from GDT

+    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+    add     edi, 8                              ; move up to next descriptor

+    add     bx, DEFAULT_HANDLER_SIZE            ; move to next entry point

+    loop    @b                                  ; loop back through again until all descriptors are initialized

+    

+    ;; at this point edi contains the offset of the descriptor for INT 20

+    ;; and bx contains the low 16 bits of the offset of the default handler

+    ;; so initialize all the rest of the descriptors with these two values...

+;    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)

+;@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+;    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+;    mov     word ptr [edi+2], 20h               ; SYS_CODE_SEL from GDT

+;    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+;    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+;    add     edi, 8                              ; move up to next descriptor

+;    loop    @b                                  ; loop back through again until all descriptors are initialized

+    

+    

+;;  DUMP    location of IDT and several of the descriptors

+;    mov     ecx, 8

+;    mov     eax, [offset Idtr + 2]

+;    mov     eax, [eax]

+;    mov     edi, 0b8000h

+;    call    PrintDword

+;    mov     esi, eax

+;    mov     edi, 0b80a0h

+;    jmp     OuterLoop

+    

+;;    

+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...

+;    mov     eax, 011111111h

+;    mov     ebx, 022222222h

+;    mov     ecx, 033333333h

+;    mov     edx, 044444444h

+;    mov     ebp, 055555555h

+;    mov     esi, 066666666h

+;    mov     edi, 077777777h

+;    push    011111111h

+;    push    022222222h

+;    push    033333333h

+;    int     119

+

+    

+    mov     esi,022000h                 ; esi = 22000

+    mov     eax,[esi+014h]              ; eax = [22014]

+    add     esi,eax                     ; esi = 22000 + [22014] = Base of EFILDR.C

+    mov     ebp,[esi+03ch]              ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C

+    add     ebp,esi

+    mov     edi,[ebp+034h]              ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase

+    mov     eax,[ebp+028h]              ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint

+    add     eax,edi                     ; eax = ImageBase + EntryPoint

+    mov     dword ptr [EfiLdrOffset],eax   ; Modify far jump instruction for correct entry point

+

+    mov     bx,word ptr[ebp+6]          ; bx = Number of sections

+    xor     eax,eax

+    mov     ax,word ptr[ebp+014h]       ; ax = Optional Header Size

+    add     ebp,eax

+    add     ebp,018h                    ; ebp = Start of 1st Section

+

+SectionLoop:

+    push    esi                         ; Save Base of EFILDR.C

+    push    edi                         ; Save ImageBase

+    add     esi,[ebp+014h]              ; esi = Base of EFILDR.C + PointerToRawData

+    add     edi,[ebp+00ch]              ; edi = ImageBase + VirtualAddress

+    mov     ecx,[ebp+010h]              ; ecs = SizeOfRawData

+

+    cld

+    shr     ecx,2

+    rep     movsd

+

+    pop     edi                         ; Restore ImageBase

+    pop     esi                         ; Restore Base of EFILDR.C

+

+    add     bp,028h                     ; ebp = ebp + 028h = Pointer to next section record

+    dec     bx

+    cmp     bx,0

+    jne     SectionLoop

+

+    movzx   eax, word ptr [Idtr]         ; get size of IDT

+    inc     eax

+    add     eax, dword ptr [Idtr + 2]    ; add to base of IDT to get location of memory map...

+    push    eax                         ; push memory map location on stack for call to EFILDR...

+

+    push    eax                         ; push return address (useless, just for stack balance)

+    db      0b8h

+EfiLdrOffset:

+    dd      000401000h                  ; Offset of EFILDR

+; mov eax, 401000h

+    push    eax

+    ret

+

+;    db      "**** DEFAULT IDT ENTRY ***",0

+    align 02h

+Halt:

+INT0:

+    push    0h      ; push error code place holder on the stack

+    push    0h

+    JmpCommonIdtEntry

+;    db      0e9h                        ; jmp 16 bit reletive 

+;    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+    

+INT1:

+    push    0h      ; push error code place holder on the stack

+    push    1h

+    JmpCommonIdtEntry

+    

+INT2:

+    push    0h      ; push error code place holder on the stack

+    push    2h

+    JmpCommonIdtEntry

+    

+INT3:

+    push    0h      ; push error code place holder on the stack

+    push    3h

+    JmpCommonIdtEntry

+    

+INT4:

+    push    0h      ; push error code place holder on the stack

+    push    4h

+    JmpCommonIdtEntry

+    

+INT5:

+    push    0h      ; push error code place holder on the stack

+    push    5h

+    JmpCommonIdtEntry

+    

+INT6:

+    push    0h      ; push error code place holder on the stack

+    push    6h

+    JmpCommonIdtEntry

+    

+INT7:

+    push    0h      ; push error code place holder on the stack

+    push    7h

+    JmpCommonIdtEntry

+    

+INT8:

+;   Double fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    8h

+    JmpCommonIdtEntry

+    

+INT9:

+    push    0h      ; push error code place holder on the stack

+    push    9h

+    JmpCommonIdtEntry

+    

+INT10:

+;   Invalid TSS causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    10

+    JmpCommonIdtEntry

+    

+INT11:

+;   Segment Not Present causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    11

+    JmpCommonIdtEntry

+    

+INT12:

+;   Stack fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    12

+    JmpCommonIdtEntry

+    

+INT13:

+;   GP fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    13

+    JmpCommonIdtEntry

+    

+INT14:

+;   Page fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    14

+    JmpCommonIdtEntry

+    

+INT15:

+    push    0h      ; push error code place holder on the stack

+    push    15

+    JmpCommonIdtEntry

+    

+INT16:

+    push    0h      ; push error code place holder on the stack

+    push    16

+    JmpCommonIdtEntry

+    

+INT17:

+;   Alignment check causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    17

+    JmpCommonIdtEntry

+    

+INT18:

+    push    0h      ; push error code place holder on the stack

+    push    18

+    JmpCommonIdtEntry

+    

+INT19:

+    push    0h      ; push error code place holder on the stack

+    push    19

+    JmpCommonIdtEntry

+

+INTUnknown:

+REPEAT  (78h - 20)

+    push    0h      ; push error code place holder on the stack

+;    push    xxh     ; push vector number

+    db      06ah

+    db      ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number

+    JmpCommonIdtEntry

+ENDM

+

+commonIdtEntry:

+    pushad

+    mov     ebp, esp

+;;

+;;  At this point the stack looks like this:

+;;

+;;      eflags

+;;      Calling CS

+;;      Calling EIP

+;;      Error code or 0

+;;      Int num or 0ffh for unknown int num

+;;      eax

+;;      ecx

+;;      edx

+;;      ebx

+;;      esp

+;;      ebp

+;;      esi

+;;      edi <------- ESP, EBP

+;;      

+

+    call    ClearScreen

+    mov     esi, offset String1

+    call    PrintString

+    mov     eax, [ebp + 32]     ;; move Int number into EAX 

+    cmp     eax, 19

+    ja      PrintDefaultString

+PrintExceptionString:

+    shl     eax, 2              ;; multiply by 4 to get offset from StringTable to actual string address

+    add     eax, offset StringTable

+    mov     esi, [eax]

+    jmp     PrintTheString

+PrintDefaultString:

+    mov     esi, offset IntUnknownString

+    ; patch Int number

+    mov     edx, eax

+    call    A2C

+    mov     [esi + 1], al

+    mov     eax, edx

+    shr     eax, 4

+    call    A2C

+    mov     [esi], al

+PrintTheString:        

+    call    PrintString

+    mov     esi, offset String2

+    call    PrintString

+    mov     eax, [ebp+44]          ; CS

+    call    PrintDword

+    mov     al, ':'

+    mov     byte ptr [edi], al

+    add     edi, 2

+    mov     eax, [ebp+40]          ; EIP

+    call    PrintDword

+    mov     esi, offset String3

+    call    PrintString

+    

+    mov     edi, 0b8140h

+    

+    mov     esi, offset StringEax     ; eax

+    call    PrintString

+    mov     eax, [ebp+28]

+    call    PrintDword

+    

+    mov     esi, offset StringEbx     ; ebx

+    call    PrintString

+    mov     eax, [ebp+16]

+    call    PrintDword

+    

+    mov     esi, offset StringEcx     ; ecx

+    call    PrintString

+    mov     eax, [ebp+24]

+    call    PrintDword

+    

+    mov     esi, offset StringEdx     ; edx

+    call    PrintString

+    mov     eax, [ebp+20]

+    call    PrintDword

+    

+    mov     esi, offset StringEcode   ; error code

+    call    PrintString

+    mov     eax, [ebp+36]

+    call    PrintDword

+    

+    mov     edi, 0b81e0h

+    

+    mov     esi, offset StringEsp     ; esp

+    call    PrintString

+    mov     eax, [ebp+12]

+    call    PrintDword

+    

+    mov     esi, offset StringEbp     ; ebp

+    call    PrintString

+    mov     eax, [ebp+8]

+    call    PrintDword

+    

+    mov     esi, offset StringEsi     ; esi

+    call    PrintString

+    mov     eax, [ebp+4]

+    call    PrintDword

+    

+    mov     esi, offset StringEdi    ; edi

+    call    PrintString

+    mov     eax, [ebp]

+    call    PrintDword

+    

+    mov     esi, offset StringEflags ; eflags

+    call    PrintString

+    mov     eax, [ebp+48]

+    call    PrintDword

+    

+    mov     edi, 0b8320h

+

+    mov     esi, ebp

+    add     esi, 52

+    mov     ecx, 8

+

+    

+OuterLoop:

+    push    ecx

+    mov     ecx, 8

+    mov     edx, edi

+

+InnerLoop:

+    mov     eax, [esi]

+    call    PrintDword

+    add     esi, 4

+    mov     al, ' '

+    mov     [edi], al

+    add     edi, 2

+    loop    InnerLoop

+

+    pop     ecx

+    add     edx, 0a0h

+    mov     edi, edx

+    loop    OuterLoop

+

+

+    mov     edi, 0b8960h

+

+    mov     eax, [ebp+40]  ; EIP

+    sub     eax, 32 * 4

+    mov     esi, eax        ; esi = eip - 32 DWORD linear (total 64 DWORD)

+

+    mov     ecx, 8

+    

+OuterLoop1:

+    push    ecx

+    mov     ecx, 8

+    mov     edx, edi

+

+InnerLoop1:

+    mov     eax, [esi]

+    call    PrintDword

+    add     esi, 4

+    mov     al, ' '

+    mov     [edi], al

+    add     edi, 2

+    loop    InnerLoop1

+

+    pop     ecx

+    add     edx, 0a0h

+    mov     edi, edx

+    loop    OuterLoop1

+

+

+

+;    wbinvd ; Ken: this intruction does not support in early than 486 arch

+@@:    

+    jmp     @b

+;

+; return

+;

+    mov     esp, ebp

+    popad

+    add     esp, 8 ; error code and INT number

+    

+    iretd

+

+

+PrintString:

+    push    eax

+@@:

+    mov     al, byte ptr [esi]

+    cmp     al, 0

+    je      @f

+    mov     byte ptr [edi], al

+    inc     esi

+    add     edi, 2

+    jmp     @b

+@@:

+    pop     eax

+    ret

+        

+;; EAX contains dword to print

+;; EDI contains memory location (screen location) to print it to

+PrintDword:

+    push    ecx

+    push    ebx

+    push    eax

+    

+    mov     ecx, 8

+looptop:

+    rol     eax, 4

+    mov     bl, al

+    and     bl, 0fh

+    add     bl, '0'

+    cmp     bl, '9'

+    jle     @f

+    add     bl, 7

+@@:

+    mov     byte ptr [edi], bl

+    add     edi, 2

+    loop    looptop

+    ;wbinvd

+    

+    pop     eax

+    pop     ebx

+    pop     ecx

+    ret

+

+ClearScreen:

+    push    eax

+    push    ecx

+    

+    mov     al, ' '

+    mov     ah, 0ch

+    mov     edi, 0b8000h

+    mov     ecx, 80 * 24

+@@:

+    mov     word ptr [edi], ax

+    add     edi, 2

+    loop    @b

+    mov     edi, 0b8000h

+    

+    pop     ecx

+    pop     eax

+

+    ret                

+        

+A2C:

+    and     al, 0fh

+    add     al, '0'

+    cmp     al, '9'

+    jle     @f

+    add     al, 7

+@@:

+    ret

+        

+String1           db  "*** INT ",0

+

+Int0String        db  "00h Divide by 0 -",0

+Int1String        db  "01h Debug exception -",0

+Int2String        db  "02h NMI -",0

+Int3String        db  "03h Breakpoint -",0

+Int4String        db  "04h Overflow -",0

+Int5String        db  "05h Bound -",0

+Int6String        db  "06h Invalid opcode -",0

+Int7String        db  "07h Device not available -",0

+Int8String        db  "08h Double fault -",0

+Int9String        db  "09h Coprocessor seg overrun (reserved) -",0

+Int10String       db  "0Ah Invalid TSS -",0

+Int11String       db  "0Bh Segment not present -",0

+Int12String       db  "0Ch Stack fault -",0

+Int13String       db  "0Dh General protection fault -",0

+Int14String       db  "0Eh Page fault -",0

+Int15String       db  "0Fh (Intel reserved) -",0

+Int16String       db  "10h Floating point error -",0

+Int17String       db  "11h Alignment check -",0

+Int18String       db  "12h Machine check -",0

+Int19String       db  "13h SIMD Floating-Point Exception -",0

+IntUnknownString  db  "??h Unknown interrupt -",0

+

+StringTable       dd  offset Int0String, offset Int1String, offset Int2String, offset Int3String, 

+                      offset Int4String, offset Int5String, offset Int6String, offset Int7String,

+                      offset Int8String, offset Int9String, offset Int10String, offset Int11String,

+                      offset Int12String, offset Int13String, offset Int14String, offset Int15String,

+                      offset Int16String, offset Int17String, offset Int18String, offset Int19String

+

+String2           db  " HALT!! *** (",0

+String3           db  ")",0

+StringEax         db  "EAX=",0

+StringEbx         db  " EBX=",0

+StringEcx         db  " ECX=",0

+StringEdx         db  " EDX=",0

+StringEcode       db  " ECODE=",0

+StringEsp         db  "ESP=",0

+StringEbp         db  " EBP=",0

+StringEsi         db  " ESI=",0

+StringEdi         db  " EDI=",0

+StringEflags      db  " EFLAGS=",0

+

+Idtr        df  0

+

+    org 21ffeh

+BlockSignature:

+    dw      0aa55h

+    

+    end

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/efi64.S b/uefi/linaro-edk2/DuetPkg/BootSector/efi64.S
new file mode 100644
index 0000000..34bd752
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/efi64.S
@@ -0,0 +1,1385 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    efi64.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+##############################################################################

+# Now in 64-bit long mode.

+##############################################################################

+

+        .486: 

+        .stack: 

+        .code: 

+        .org 0x21000

+

+.global _start

+_start:

+

+.equ                 DEFAULT_HANDLER_SIZE, INT1 - INT0

+

+.macro jmpCommonIdtEntry  

+    # jmp     commonIdtEntry - this must be hand coded to keep the assembler from

+    #                          using a 8 bit reletive jump when the entries are

+    #                          within 255 bytes of the common entry.  This must

+    #                          be done to maintain the consistency of the size

+    #                          of entry points...

+    .byte   0xe9                     # jmp 16 bit relative

+    .long   commonIdtEntry - . - 4   # offset to jump to

+.endm

+

+

+Start:  

+

+    movl    $0x001fffe8,%esp # make final stack aligned

+

+    # set OSFXSR and OSXMMEXCPT because some code will use XMM register

+    .byte 0xf

+    .byte 0x20

+    .byte 0xe0

+#    mov rax, cr4

+    btsl $9,%eax

+    btsl $0xa,%eax

+    .byte 0xf

+    .byte 0x22

+    .byte 0xe0

+#    mov cr4, rax

+

+    call    ClearScreen

+

+    # Populate IDT with meaningful offsets for exception handlers...

+    movl    $Idtr, %eax

+    sidt    (%eax)                      # get fword address of IDT

+    

+

+    movl    $Halt, %eax

+    movl    %eax,%ebx                   # use bx to copy 15..0 to descriptors

+    shrl    $16,%eax                    # use ax to copy 31..16 to descriptors 

+                                        # 63..32 of descriptors is 0

+    movl    $0x78,%ecx                  # 78h IDT entries to initialize with unique entry points (exceptions)

+    movl    $(Idtr + 2), %esi

+    movl    (%esi),%edi

+

+LOOP_1:                                         # loop through all IDT entries exception handlers and initialize to default handler

+    movw    %bx, (%edi)                         # write bits 15..0 of offset

+    movw    $0x38, 2(%edi)                      # SYS_CODE_SEL64 from GDT

+    movw    $(0x0e00 | 0x8000), 4(%edi)         # type = 386 interrupt gate, present

+    movw    %ax, 6(%edi)                        # write bits 31..16 of offset

+    movl    $0, 8(%edi)                         # write bits 31..16 of offset  

+    addl    $16, %edi                           # move up to next descriptor

+    addw    $DEFAULT_HANDLER_SIZE, %bx          # move to next entry point

+    loopl   LOOP_1                              # loop back through again until all descriptors are initialized

+

+    ## at this point edi contains the offset of the descriptor for INT 20

+    ## and bx contains the low 16 bits of the offset of the default handler

+    ## so initialize all the rest of the descriptors with these two values...

+#    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)

+#@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+#    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+#    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT

+#    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+#    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+#    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset

+#    add     edi, 16                             ; move up to next descriptor

+#    loop    @b                                  ; loop back through again until all descriptors are initialized

+

+

+##  DUMP    location of IDT and several of the descriptors

+#    mov     ecx, 8

+#    mov     eax, [offset Idtr + 2]

+#    mov     eax, [eax]

+#    mov     edi, 0b8000h

+#    call    PrintQword

+#    mov     esi, eax

+#    mov     edi, 0b80a0h

+#    jmp     OuterLoop

+

+##    

+## just for fun, let's do a software interrupt to see if we correctly land in the exception handler...

+#    mov     eax, 011111111h

+#    mov     ebx, 022222222h

+#    mov     ecx, 033333333h

+#    mov     edx, 044444444h

+#    mov     ebp, 055555555h

+#    mov     esi, 066666666h

+#    mov     edi, 077777777h

+#    push    011111111h

+#    push    022222222h

+#    push    033333333h

+#    int     119

+

+    movl    $0x22000,%esi               # esi = 22000

+    movl    0x14(%esi),%eax             # eax = [22014]

+    addl    %eax,%esi                   # esi = 22000 + [22014] = Base of EFILDR.C

+    movl    0x3c(%esi),%ebp             # ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C

+    addl    %esi,%ebp

+    movl    0x30(%ebp),%edi             # edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)

+    movl    0x28(%ebp),%eax             # eax = [[22000 + [22014] + 3c] + 24] = EntryPoint

+    addl    %edi,%eax                   # eax = ImageBase + EntryPoint

+    movl    $EfiLdrOffset, %ebx

+    movl    %eax, (%ebx)                # Modify far jump instruction for correct entry point

+

+    movw    6(%ebp), %bx                # bx = Number of sections

+    xorl    %eax,%eax

+    movw    0x14(%ebp), %ax             # ax = Optional Header Size

+    addl    %eax,%ebp

+    addl    $0x18,%ebp                  # ebp = Start of 1st Section

+

+SectionLoop: 

+    pushl   %esi                        # Save Base of EFILDR.C

+    pushl   %edi                        # Save ImageBase

+    addl    0x14(%ebp),%esi             # esi = Base of EFILDR.C + PointerToRawData

+    addl    0x0c(%ebp),%edi             # edi = ImageBase + VirtualAddress

+    movl    0x10(%ebp),%ecx             # ecs = SizeOfRawData

+

+    cld

+    shrl    $2,%ecx

+    rep

+    movsl

+

+    popl    %edi                        # Restore ImageBase

+    popl    %esi                        # Restore Base of EFILDR.C

+

+    addw    $0x28,%bp                   # ebp = ebp + 028h = Pointer to next section record

+    .byte 0x66

+    .byte 0xff

+    .byte 0xcb

+#    dec     bx

+    cmpw    $0,%bx

+    jne     SectionLoop

+

+    movl    $Idtr, %edx                  # get size of IDT

+    movzxw  (%edx), %eax

+    .byte 0xff

+    .byte 0xc0

+#    inc     eax

+    addl    2(%edx), %eax                # add to base of IDT to get location of memory map...

+    xorl    %ecx,%ecx

+    movl    %eax,%ecx                    # put argument to RCX

+

+    .byte 0x48

+    .byte 0xc7

+    .byte 0xc0

+EfiLdrOffset: 

+    .long 0x00401000                    # Offset of EFILDR

+#   mov rax, 401000h

+    .byte 0x50

+#   push rax

+

+# ret

+    .byte 0xc3

+

+#    db      "**** DEFAULT IDT ENTRY ***",0

+    .p2align 1

+Halt: 

+INT0: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x0

+    jmpCommonIdtEntry 

+#    db      0e9h                        ; jmp 16 bit reletive 

+#    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+

+INT1: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x1

+    jmpCommonIdtEntry 

+

+INT2: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x2

+    jmpCommonIdtEntry 

+

+INT3: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x3

+    jmpCommonIdtEntry 

+

+INT4: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x4

+    jmpCommonIdtEntry 

+

+INT5: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x5

+    jmpCommonIdtEntry 

+

+INT6: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x6

+    jmpCommonIdtEntry 

+

+INT7: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x7

+    jmpCommonIdtEntry 

+

+INT8: 

+#   Double fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $0x8

+    jmpCommonIdtEntry 

+

+INT9: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $0x9

+    jmpCommonIdtEntry 

+

+INT10: 

+#   Invalid TSS causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $10

+    jmpCommonIdtEntry 

+

+INT11: 

+#   Segment Not Present causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $11

+    jmpCommonIdtEntry 

+

+INT12: 

+#   Stack fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $12

+    jmpCommonIdtEntry 

+

+INT13: 

+#   GP fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $13

+    jmpCommonIdtEntry 

+

+INT14: 

+#   Page fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $14

+    jmpCommonIdtEntry 

+

+INT15: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $15

+    jmpCommonIdtEntry 

+

+INT16: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $16

+    jmpCommonIdtEntry 

+

+INT17: 

+#   Alignment check causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    pushl   $17

+    jmpCommonIdtEntry 

+

+INT18: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $18

+    jmpCommonIdtEntry 

+

+INT19: 

+    pushl   $0x0    # push error code place holder on the stack

+    pushl   $19

+    jmpCommonIdtEntry 

+

+INTUnknown: 

+# The following segment repeats (0x78 - 20) times:

+# No. 1

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 2

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 3

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 4

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 5

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 6

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 7

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 8

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 9

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 10

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 11

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 12

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 13

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 14

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 15

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 16

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 17

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 18

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 19

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 20

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 21

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 22

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 23

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 24

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 25

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 26

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 27

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 28

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 29

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 30

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 31

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 32

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 33

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 34

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 35

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 36

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 37

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 38

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 39

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 40

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 41

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 42

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 43

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 44

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 45

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 46

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 47

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 48

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 49

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 50

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 51

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 52

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 53

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 54

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 55

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 56

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 57

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 58

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 59

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 60

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 61

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 62

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 63

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 64

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 65

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 66

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 67

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 68

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 69

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 70

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 71

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 72

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 73

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 74

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 75

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 76

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 77

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 78

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 79

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 80

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 81

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 82

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 83

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 84

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 85

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 86

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 87

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 88

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 89

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 90

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 91

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 92

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 93

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 94

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 95

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 96

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 97

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 98

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 99

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+# No. 100

+    pushl   $0x0    # push error code place holder on the stack

+#    push    xxh     ; push vector number

+    .byte 0x6a

+    .byte      ( . - INTUnknown - 3 ) / 9 + 20   # vector number

+    jmpCommonIdtEntry 

+

+

+commonIdtEntry: 

+    pushl   %eax

+    pushl   %ecx

+    pushl   %edx

+    pushl   %ebx

+    pushl   %esp

+    pushl   %ebp

+    pushl   %esi

+    pushl   %edi

+    .byte 0x41

+    .byte 0x50

+#    push    r8

+    .byte 0x41

+    .byte 0x51

+#    push    r9

+    .byte 0x41

+    .byte 0x52

+#    push    r10

+    .byte 0x41

+    .byte 0x53

+#    push    r11

+    .byte 0x41

+    .byte 0x54

+#    push    r12

+    .byte 0x41

+    .byte 0x55

+#    push    r13

+    .byte 0x41

+    .byte 0x56

+#    push    r14

+    .byte 0x41

+    .byte 0x57

+#    push    r15

+    .byte 0x48

+    movl    %esp,%ebp

+#    mov     rbp, rsp

+

+##

+##  At this point the stack looks like this:

+##

+##      Calling SS

+##      Calling RSP

+##      rflags

+##      Calling CS

+##      Calling RIP

+##      Error code or 0

+##      Int num or 0ffh for unknown int num

+##      rax

+##      rcx

+##      rdx

+##      rbx

+##      rsp

+##      rbp

+##      rsi

+##      rdi

+##      r8

+##      r9

+##      r10

+##      r11

+##      r12

+##      r13

+##      r14

+##      r15 <------- RSP, RBP

+##      

+

+    call    ClearScreen

+    movl    $String1, %esi 

+    call    PrintString

+    .byte 0x48

+    movl    16*8(%ebp),%eax       ## move Int number into RAX 

+    .byte 0x48

+    cmpl    $18,%eax

+    ja      PrintDefaultString

+PrintExceptionString: 

+    shll    $3,%eax             ## multiply by 8 to get offset from StringTable to actual string address

+    addl    $StringTable, %eax

+    movl    (%eax),%esi

+    jmp     PrintTheString

+PrintDefaultString: 

+    movl    $IntUnknownString, %esi

+    # patch Int number

+    movl    %eax,%edx

+    call    A2C

+    movb    %al,1(%esi)

+    movl    %edx,%eax

+    shrl    $4,%eax

+    call    A2C

+    movb    %al,(%esi)

+PrintTheString:        

+    call    PrintString

+    movl    $String2, %esi

+    call    PrintString

+    .byte 0x48

+    movl    19*8(%ebp),%eax    # CS

+    call    PrintQword

+    movb    $':', %al

+    movb    %al, (%edi)

+    addl    $2,%edi

+    .byte 0x48

+    movl    18*8(%ebp),%eax    # RIP

+    call    PrintQword

+    movl    $String3, %esi

+    call    PrintString

+

+    movl    $0xb8140,%edi

+

+    movl    $StringRax, %esi

+    call    PrintString

+    .byte 0x48

+    movl    15*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringRcx, %esi

+    call    PrintString

+    .byte 0x48

+    movl    14*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringRdx, %esi

+    call    PrintString

+    .byte 0x48

+    movl    13*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb81e0,%edi

+

+    movl    $StringRbx, %esi

+    call    PrintString

+    .byte 0x48

+    movl    12*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringRsp, %esi

+    call    PrintString

+    .byte 0x48

+    movl    21*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringRbp, %esi

+    call    PrintString

+    .byte 0x48

+    movl    10*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb8280,%edi

+

+    movl    $StringRsi, %esi

+    call    PrintString

+    .byte 0x48

+    movl    9*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringRdi, %esi

+    call    PrintString

+    .byte 0x48

+    movl    8*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringEcode, %esi

+    call    PrintString

+    .byte 0x48

+    movl    17*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb8320,%edi

+

+    movl    $StringR8, %esi

+    call    PrintString

+    .byte 0x48

+    movl    7*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringR9, %esi

+    call    PrintString

+    .byte 0x48

+    movl    6*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringR10, %esi

+    call    PrintString

+    .byte 0x48

+    movl    5*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb83c0,%edi

+

+    movl    $StringR11, %esi

+    call    PrintString

+    .byte 0x48

+    movl    4*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringR12, %esi

+    call    PrintString

+    .byte 0x48

+    movl    3*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringR13, %esi

+    call    PrintString

+    .byte 0x48

+    movl    2*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb8460,%edi

+

+    movl    $StringR14, %esi

+    call    PrintString

+    .byte 0x48

+    movl    1*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringR15, %esi

+    call    PrintString

+    .byte 0x48

+    movl    0*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $StringSs, %esi

+    call    PrintString

+    .byte 0x48

+    movl    22*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb8500,%edi

+

+    movl    $StringRflags, %esi

+    call    PrintString

+    .byte 0x48

+    movl    20*8(%ebp),%eax

+    call    PrintQword

+

+    movl    $0xb8640,%edi

+

+    movl    %ebp,%esi

+    addl    $23*8,%esi

+    movl    $4,%ecx

+

+

+OuterLoop: 

+    pushl   %ecx

+    movl    $4,%ecx

+    .byte 0x48

+    movl    %edi,%edx

+

+InnerLoop: 

+    .byte 0x48

+    movl    (%esi),%eax

+    call    PrintQword

+    addl    $8,%esi

+    movb    $0x20, %al       # blank character

+    movb    %al,(%edi)

+    addl    $2,%edi

+    loop    InnerLoop

+

+    popl    %ecx

+    addl    $0xa0,%edx

+    movl    %edx,%edi

+    loop    OuterLoop

+

+

+    movl    $0xb8960,%edi

+

+    .byte 0x48

+    movl    18*8(%ebp),%eax  # RIP

+    subl    $8*8,%eax

+    .byte 0x48

+    movl    %eax,%esi       # esi = rip - 8 QWORD linear (total 16 QWORD)

+

+    movl    $4,%ecx

+

+OuterLoop1: 

+    pushl   %ecx

+    movl    $4,%ecx

+    movl    %edi,%edx

+

+InnerLoop1: 

+    .byte 0x48

+    movl    (%esi),%eax

+    call    PrintQword

+    addl    $8,%esi

+    movb    $0x20, %al     # blank character

+    movb    %al,(%edi)

+    addl    $2,%edi

+    loop    InnerLoop1

+

+    popl    %ecx

+    addl    $0xa0,%edx

+    movl    %edx,%edi

+    loop    OuterLoop1

+

+

+

+    #wbinvd

+LN_C1:    

+    jmp     LN_C1

+

+#

+# return

+#

+    movl    %ebp,%esp

+#    mov     rsp, rbp

+    .byte 0x41

+    .byte 0x5f

+#    pop    r15

+    .byte 0x41

+    .byte 0x5e

+#    pop    r14

+    .byte 0x41

+    .byte 0x5d

+#    pop    r13

+    .byte 0x41

+    .byte 0x5c

+#    pop    r12

+    .byte 0x41

+    .byte 0x5b

+#    pop    r11

+    .byte 0x41

+    .byte 0x5a

+#    pop    r10

+    .byte 0x41

+    .byte 0x59

+#    pop    r9

+    .byte 0x41

+    .byte 0x58

+#    pop    r8

+    popl   %edi

+    popl   %esi

+    popl   %ebp

+    popl   %eax # esp

+    popl   %ebx

+    popl   %edx

+    popl   %ecx

+    popl   %eax

+

+    .byte 0x48

+    .byte 0x83

+    .byte 0xc4

+    .byte 0x10

+#    add    esp, 16 ; error code and INT number

+

+    .byte 0x48

+    .byte 0xcf

+#    iretq

+

+PrintString: 

+    pushl   %eax

+LN_C2: 

+    movb    (%esi), %al

+    cmpb    $0,%al

+    je      LN_C3

+    movb    %al, (%edi)

+    .byte 0xff

+    .byte 0xc6

+#    inc     esi

+    addl    $2,%edi

+    jmp     LN_C2

+LN_C3: 

+    popl    %eax

+    ret

+

+## RAX contains qword to print

+## RDI contains memory location (screen location) to print it to

+PrintQword: 

+    pushl   %ecx

+    pushl   %ebx

+    pushl   %eax

+

+    .byte 0x48

+    .byte 0xc7

+    .byte 0xc1

+    .long 16

+#    mov     rcx, 16

+looptop: 

+    .byte 0x48

+    roll    $4,%eax

+    movb    %al,%bl

+    andb    $0xf,%bl

+    addb    $'0', %bl

+    cmpb    $'9', %bl

+    jle     LN_C4

+    addb    $7,%bl

+LN_C4: 

+    movb %bl, (%edi)

+    addl    $2,%edi

+    loop    looptop

+    #wbinvd

+

+    popl    %eax

+    popl    %ebx

+    popl    %ecx

+    ret

+

+ClearScreen: 

+    pushl   %eax

+    pushl   %ecx

+

+    movb    $0x20, %al       # blank character

+    movb    $0xc,%ah

+    movl    $0xb8000,%edi

+    movl    $80*24,%ecx

+LN_C5: 

+    movw    %ax, (%edi)

+    addl    $2,%edi

+    loop    LN_C5

+    movl    $0xb8000,%edi

+

+    popl    %ecx

+    popl    %eax

+

+    ret

+

+A2C: 

+    andb    $0xf,%al

+    addb    $'0', %al

+    cmpb    $'9', %al

+    jle     LN_C6

+    addb    $7,%al

+LN_C6: 

+    ret

+

+String1:            .asciz      "*** INT "

+

+Int0String:         .asciz      "00h Divide by 0 -"

+Int1String:         .asciz      "01h Debug exception -"

+Int2String:         .asciz      "02h NMI -"

+Int3String:         .asciz      "03h Breakpoint -"

+Int4String:         .asciz      "04h Overflow -"

+Int5String:         .asciz      "05h Bound -"

+Int6String:         .asciz      "06h Invalid opcode -"

+Int7String:         .asciz      "07h Device not available -"

+Int8String:         .asciz      "08h Double fault -"

+Int9String:         .asciz      "09h Coprocessor seg overrun (reserved) -"

+Int10String:        .asciz      "0Ah Invalid TSS -"

+Int11String:        .asciz      "0Bh Segment not present -"

+Int12String:        .asciz      "0Ch Stack fault -"

+Int13String:        .asciz      "0Dh General protection fault -"

+Int14String:        .asciz      "0Eh Page fault -"

+Int15String:        .asciz      "0Fh (Intel reserved) -"

+Int16String:        .asciz      "10h Floating point error -"

+Int17String:        .asciz      "11h Alignment check -"

+Int18String:        .asciz      "12h Machine check -"

+Int19String:        .asciz      "13h SIMD Floating-Point Exception -"

+IntUnknownString:   .asciz      "??h Unknown interrupt -"

+

+StringTable:   .long  Int0String, 0, Int1String, 0, Int2String, 0, Int3String, 0,  \

+                      Int4String, 0, Int5String, 0, Int6String, 0, Int7String, 0,  \

+                      Int8String, 0, Int9String, 0, Int10String, 0, Int11String, 0,  \

+                      Int12String, 0, Int13String, 0, Int14String, 0, Int15String, 0,  \

+                      Int16String, 0, Int17String, 0, Int18String, 0, Int19String, 0

+

+String2:           .asciz  " HALT!! *** ("

+String3:           .asciz  ")"

+StringRax:         .asciz  "RAX="

+StringRcx:         .asciz  " RCX="

+StringRdx:         .asciz  " RDX="

+StringRbx:         .asciz  "RBX="

+StringRsp:         .asciz  " RSP="

+StringRbp:         .asciz  " RBP="

+StringRsi:         .asciz  "RSI="

+StringRdi:         .asciz  " RDI="

+StringEcode:       .asciz  " ECODE="

+StringR8:          .asciz  "R8 ="

+StringR9:          .asciz  " R9 ="

+StringR10:         .asciz  " R10="

+StringR11:         .asciz  "R11="

+StringR12:         .asciz  " R12="

+StringR13:         .asciz  " R13="

+StringR14:         .asciz  "R14="

+StringR15:         .asciz  " R15="

+StringSs:          .asciz  " SS ="

+StringRflags:      .asciz  "RFLAGS="

+

+Idtr:        .float  0

+            .float  0

+

+    .org 0x21ffe

+BlockSignature: 

+    .word 0xaa55

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/efi64.asm b/uefi/linaro-edk2/DuetPkg/BootSector/efi64.asm
new file mode 100644
index 0000000..ee6f9fd
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/efi64.asm
@@ -0,0 +1,787 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    efi64.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; Now in 64-bit long mode.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        .486

+        .model  flat        

+        .stack

+        .code

+        org 21000h

+        

+DEFAULT_HANDLER_SIZE EQU INT1 - INT0

+

+JmpCommonIdtEntry  macro

+    ; jmp     commonIdtEntry - this must be hand coded to keep the assembler from

+    ;                          using a 8 bit reletive jump when the entries are

+    ;                          within 255 bytes of the common entry.  This must

+    ;                          be done to maintain the consistency of the size

+    ;                          of entry points...

+    db      0e9h                        ; jmp 16 bit reletive 

+    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+endm    

+

+        

+Start:  

+

+    mov     esp,0001fffe8h ; make final stack aligned

+

+    ; set OSFXSR and OSXMMEXCPT because some code will use XMM register

+    db 0fh

+    db 20h

+    db 0e0h

+;    mov rax, cr4

+    bts eax, 9

+    bts eax, 0ah

+    db 0fh

+    db 22h

+    db 0e0h

+;    mov cr4, rax

+

+    call    ClearScreen

+

+    ; Populate IDT with meaningful offsets for exception handlers...

+    mov     eax, offset Idtr

+    sidt    fword ptr [eax]             ; get fword address of IDT

+

+    mov     eax, offset Halt

+    mov     ebx, eax                    ; use bx to copy 15..0 to descriptors

+    shr     eax, 16                     ; use ax to copy 31..16 to descriptors 

+                                        ; 63..32 of descriptors is 0

+    mov     ecx, 78h                    ; 78h IDT entries to initialize with unique entry points (exceptions)

+    mov     esi, [offset Idtr + 2]

+    mov     edi, [esi]

+

+@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT

+    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset

+    add     edi, 16                             ; move up to next descriptor

+    add     bx, DEFAULT_HANDLER_SIZE            ; move to next entry point

+    loop    @b                                  ; loop back through again until all descriptors are initialized

+    

+    ;; at this point edi contains the offset of the descriptor for INT 20

+    ;; and bx contains the low 16 bits of the offset of the default handler

+    ;; so initialize all the rest of the descriptors with these two values...

+;    mov     ecx, 101                            ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h)

+;@@:                                             ; loop through all IDT entries exception handlers and initialize to default handler

+;    mov     word ptr [edi], bx                  ; write bits 15..0 of offset

+;    mov     word ptr [edi+2], 38h               ; SYS_CODE64_SEL from GDT

+;    mov     word ptr [edi+4], 0e00h OR 8000h    ; type = 386 interrupt gate, present

+;    mov     word ptr [edi+6], ax                ; write bits 31..16 of offset

+;    mov     dword ptr [edi+8], 0                ; write bits 63..32 of offset

+;    add     edi, 16                             ; move up to next descriptor

+;    loop    @b                                  ; loop back through again until all descriptors are initialized

+    

+    

+;;  DUMP    location of IDT and several of the descriptors

+;    mov     ecx, 8

+;    mov     eax, [offset Idtr + 2]

+;    mov     eax, [eax]

+;    mov     edi, 0b8000h

+;    call    PrintQword

+;    mov     esi, eax

+;    mov     edi, 0b80a0h

+;    jmp     OuterLoop

+    

+;;    

+;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler...

+;    mov     eax, 011111111h

+;    mov     ebx, 022222222h

+;    mov     ecx, 033333333h

+;    mov     edx, 044444444h

+;    mov     ebp, 055555555h

+;    mov     esi, 066666666h

+;    mov     edi, 077777777h

+;    push    011111111h

+;    push    022222222h

+;    push    033333333h

+;    int     119

+

+    mov     esi,022000h                 ; esi = 22000

+    mov     eax,[esi+014h]              ; eax = [22014]

+    add     esi,eax                     ; esi = 22000 + [22014] = Base of EFILDR.C

+    mov     ebp,[esi+03ch]              ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C

+    add     ebp,esi

+    mov     edi,[ebp+030h]              ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore)

+    mov     eax,[ebp+028h]              ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint

+    add     eax,edi                     ; eax = ImageBase + EntryPoint

+    mov     ebx, offset EfiLdrOffset

+    mov     dword ptr [ebx],eax         ; Modify far jump instruction for correct entry point

+

+    mov     bx,word ptr[ebp+6]          ; bx = Number of sections

+    xor     eax,eax

+    mov     ax,word ptr[ebp+014h]       ; ax = Optional Header Size

+    add     ebp,eax

+    add     ebp,018h                    ; ebp = Start of 1st Section

+

+SectionLoop:

+    push    esi                         ; Save Base of EFILDR.C

+    push    edi                         ; Save ImageBase

+    add     esi,[ebp+014h]              ; esi = Base of EFILDR.C + PointerToRawData

+    add     edi,[ebp+00ch]              ; edi = ImageBase + VirtualAddress

+    mov     ecx,[ebp+010h]              ; ecs = SizeOfRawData

+

+    cld

+    shr     ecx,2

+    rep     movsd

+

+    pop     edi                         ; Restore ImageBase

+    pop     esi                         ; Restore Base of EFILDR.C

+

+    add     bp,028h                     ; ebp = ebp + 028h = Pointer to next section record

+    db 66h

+    db 0ffh

+    db 0cbh

+;    dec     bx

+    cmp     bx,0

+    jne     SectionLoop

+

+    mov     edx, offset Idtr

+    movzx   eax, word ptr [edx]          ; get size of IDT

+    db 0ffh

+    db 0c0h

+;    inc     eax

+    add     eax, dword ptr [edx + 2]     ; add to base of IDT to get location of memory map...

+    xor     ecx, ecx

+    mov     ecx, eax                     ; put argument to RCX

+

+    db 48h

+    db 0c7h

+    db 0c0h

+EfiLdrOffset:

+    dd      000401000h                  ; Offset of EFILDR

+;   mov rax, 401000h

+    db 50h

+;   push rax

+

+; ret

+    db 0c3h

+

+;    db      "**** DEFAULT IDT ENTRY ***",0

+    align 02h

+Halt:

+INT0:

+    push    0h      ; push error code place holder on the stack

+    push    0h

+    JmpCommonIdtEntry

+;    db      0e9h                        ; jmp 16 bit reletive 

+;    dd      commonIdtEntry - $ - 4      ;  offset to jump to

+    

+INT1:

+    push    0h      ; push error code place holder on the stack

+    push    1h

+    JmpCommonIdtEntry

+    

+INT2:

+    push    0h      ; push error code place holder on the stack

+    push    2h

+    JmpCommonIdtEntry

+    

+INT3:

+    push    0h      ; push error code place holder on the stack

+    push    3h

+    JmpCommonIdtEntry

+    

+INT4:

+    push    0h      ; push error code place holder on the stack

+    push    4h

+    JmpCommonIdtEntry

+    

+INT5:

+    push    0h      ; push error code place holder on the stack

+    push    5h

+    JmpCommonIdtEntry

+    

+INT6:

+    push    0h      ; push error code place holder on the stack

+    push    6h

+    JmpCommonIdtEntry

+    

+INT7:

+    push    0h      ; push error code place holder on the stack

+    push    7h

+    JmpCommonIdtEntry

+    

+INT8:

+;   Double fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    8h

+    JmpCommonIdtEntry

+    

+INT9:

+    push    0h      ; push error code place holder on the stack

+    push    9h

+    JmpCommonIdtEntry

+    

+INT10:

+;   Invalid TSS causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    10

+    JmpCommonIdtEntry

+    

+INT11:

+;   Segment Not Present causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    11

+    JmpCommonIdtEntry

+    

+INT12:

+;   Stack fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    12

+    JmpCommonIdtEntry

+    

+INT13:

+;   GP fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    13

+    JmpCommonIdtEntry

+    

+INT14:

+;   Page fault causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    14

+    JmpCommonIdtEntry

+    

+INT15:

+    push    0h      ; push error code place holder on the stack

+    push    15

+    JmpCommonIdtEntry

+    

+INT16:

+    push    0h      ; push error code place holder on the stack

+    push    16

+    JmpCommonIdtEntry

+    

+INT17:

+;   Alignment check causes an error code to be pushed so no phony push necessary

+    nop

+    nop

+    push    17

+    JmpCommonIdtEntry

+    

+INT18:

+    push    0h      ; push error code place holder on the stack

+    push    18

+    JmpCommonIdtEntry

+    

+INT19:

+    push    0h      ; push error code place holder on the stack

+    push    19

+    JmpCommonIdtEntry

+

+INTUnknown:

+REPEAT  (78h - 20)

+    push    0h      ; push error code place holder on the stack

+;    push    xxh     ; push vector number

+    db      06ah

+    db      ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number

+    JmpCommonIdtEntry

+ENDM

+

+commonIdtEntry:

+    push    eax

+    push    ecx

+    push    edx

+    push    ebx

+    push    esp

+    push    ebp

+    push    esi

+    push    edi

+    db 41h

+    db 50h

+;    push    r8

+    db 41h

+    db 51h

+;    push    r9

+    db 41h

+    db 52h

+;    push    r10

+    db 41h

+    db 53h

+;    push    r11

+    db 41h

+    db 54h

+;    push    r12

+    db 41h

+    db 55h

+;    push    r13

+    db 41h

+    db 56h

+;    push    r14

+    db 41h

+    db 57h

+;    push    r15

+    db 48h

+    mov     ebp, esp

+;    mov     rbp, rsp

+

+;;

+;;  At this point the stack looks like this:

+;;

+;;      Calling SS

+;;      Calling RSP

+;;      rflags

+;;      Calling CS

+;;      Calling RIP

+;;      Error code or 0

+;;      Int num or 0ffh for unknown int num

+;;      rax

+;;      rcx

+;;      rdx

+;;      rbx

+;;      rsp

+;;      rbp

+;;      rsi

+;;      rdi

+;;      r8

+;;      r9

+;;      r10

+;;      r11

+;;      r12

+;;      r13

+;;      r14

+;;      r15 <------- RSP, RBP

+;;      

+

+    call    ClearScreen

+    mov     esi, offset String1

+    call    PrintString

+    db 48h

+    mov     eax, [ebp + 16*8]     ;; move Int number into RAX 

+    db 48h

+    cmp     eax, 18

+    ja      PrintDefaultString

+PrintExceptionString:

+    shl     eax, 3              ;; multiply by 8 to get offset from StringTable to actual string address

+    add     eax, offset StringTable

+    mov     esi, [eax]

+    jmp     PrintTheString

+PrintDefaultString:

+    mov     esi, offset IntUnknownString

+    ; patch Int number

+    mov     edx, eax

+    call    A2C

+    mov     [esi + 1], al

+    mov     eax, edx

+    shr     eax, 4

+    call    A2C

+    mov     [esi], al

+PrintTheString:        

+    call    PrintString

+    mov     esi, offset String2

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+19*8]    ; CS

+    call    PrintQword

+    mov     al, ':'

+    mov     byte ptr [edi], al

+    add     edi, 2

+    db 48h

+    mov     eax, [ebp+18*8]    ; RIP

+    call    PrintQword

+    mov     esi, offset String3

+    call    PrintString

+    

+    mov     edi, 0b8140h

+    

+    mov     esi, offset StringRax     ; rax

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+15*8]

+    call    PrintQword

+   

+    mov     esi, offset StringRcx     ; rcx

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+14*8]

+    call    PrintQword

+    

+    mov     esi, offset StringRdx     ; rdx

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+13*8]

+    call    PrintQword

+    

+    mov     edi, 0b81e0h

+    

+    mov     esi, offset StringRbx     ; rbx

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+12*8]

+    call    PrintQword

+     

+    mov     esi, offset StringRsp     ; rsp

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+21*8]

+    call    PrintQword

+    

+    mov     esi, offset StringRbp     ; rbp

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+10*8]

+    call    PrintQword

+    

+    mov     edi, 0b8280h

+     

+    mov     esi, offset StringRsi     ; rsi

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+9*8]

+    call    PrintQword

+    

+    mov     esi, offset StringRdi     ; rdi

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+8*8]

+    call    PrintQword

+    

+    mov     esi, offset StringEcode   ; error code

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+17*8]

+    call    PrintQword

+    

+    mov     edi, 0b8320h

+ 

+    mov     esi, offset StringR8      ; r8

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+7*8]

+    call    PrintQword

+

+    mov     esi, offset StringR9      ; r9

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+6*8]

+    call    PrintQword

+

+    mov     esi, offset StringR10     ; r10

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+5*8]

+    call    PrintQword

+

+    mov     edi, 0b83c0h

+

+    mov     esi, offset StringR11     ; r11

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+4*8]

+    call    PrintQword

+

+    mov     esi, offset StringR12     ; r12

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+3*8]

+    call    PrintQword

+

+    mov     esi, offset StringR13     ; r13

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+2*8]

+    call    PrintQword

+ 

+    mov     edi, 0b8460h

+

+    mov     esi, offset StringR14     ; r14

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+1*8]

+    call    PrintQword

+ 

+    mov     esi, offset StringR15     ; r15

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+0*8]

+    call    PrintQword

+

+    mov     esi, offset StringSs      ; ss

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+22*8]

+    call    PrintQword

+  

+    mov     edi, 0b8500h

+

+    mov     esi, offset StringRflags  ; rflags

+    call    PrintString

+    db 48h

+    mov     eax, [ebp+20*8]

+    call    PrintQword

+    

+    mov     edi, 0b8640h

+

+    mov     esi, ebp

+    add     esi, 23*8

+    mov     ecx, 4

+

+    

+OuterLoop:

+    push    ecx

+    mov     ecx, 4

+    db 48h

+    mov     edx, edi

+

+InnerLoop:

+    db 48h

+    mov     eax, [esi]

+    call    PrintQword

+    add     esi, 8

+    mov     al, ' '

+    mov     [edi], al

+    add     edi, 2

+    loop    InnerLoop

+

+    pop     ecx

+    add     edx, 0a0h

+    mov     edi, edx

+    loop    OuterLoop

+

+

+    mov     edi, 0b8960h

+

+    db 48h

+    mov     eax, [ebp+18*8]  ; RIP

+    sub     eax, 8 * 8

+    db 48h

+    mov     esi, eax        ; esi = rip - 8 QWORD linear (total 16 QWORD)

+

+    mov     ecx, 4

+    

+OuterLoop1:

+    push    ecx

+    mov     ecx, 4

+    mov     edx, edi

+

+InnerLoop1:

+    db 48h

+    mov     eax, [esi]

+    call    PrintQword

+    add     esi, 8

+    mov     al, ' '

+    mov     [edi], al

+    add     edi, 2

+    loop    InnerLoop1

+

+    pop     ecx

+    add     edx, 0a0h

+    mov     edi, edx

+    loop    OuterLoop1

+

+

+

+    ;wbinvd

+@@:    

+    jmp     @b

+

+;

+; return

+;

+    mov     esp, ebp

+;    mov     rsp, rbp

+    db 41h

+    db 5fh

+;    pop    r15

+    db 41h

+    db 5eh

+;    pop    r14

+    db 41h

+    db 5dh

+;    pop    r13

+    db 41h

+    db 5ch

+;    pop    r12

+    db 41h

+    db 5bh

+;    pop    r11

+    db 41h

+    db 5ah

+;    pop    r10

+    db 41h

+    db 59h

+;    pop    r9

+    db 41h

+    db 58h

+;    pop    r8

+    pop    edi

+    pop    esi

+    pop    ebp

+    pop    eax ; esp

+    pop    ebx

+    pop    edx

+    pop    ecx

+    pop    eax

+ 

+    db 48h

+    db 83h

+    db 0c4h

+    db 10h   

+;    add    esp, 16 ; error code and INT number

+

+    db 48h

+    db 0cfh

+;    iretq

+

+PrintString:

+    push    eax

+@@:

+    mov     al, byte ptr [esi]

+    cmp     al, 0

+    je      @f

+    mov     byte ptr [edi], al

+    db 0ffh

+    db 0c6h

+;    inc     esi

+    add     edi, 2

+    jmp     @b

+@@:

+    pop     eax

+    ret

+        

+;; RAX contains qword to print

+;; RDI contains memory location (screen location) to print it to

+PrintQword:

+    push    ecx

+    push    ebx

+    push    eax

+    

+    db 48h

+    db 0c7h

+    db 0c1h

+    dd 16

+;    mov     rcx, 16

+looptop:

+    db 48h

+    rol     eax, 4

+    mov     bl, al

+    and     bl, 0fh

+    add     bl, '0'

+    cmp     bl, '9'

+    jle     @f

+    add     bl, 7

+@@:

+    mov     byte ptr [edi], bl

+    add     edi, 2

+    loop    looptop

+    ;wbinvd

+    

+    pop     eax

+    pop     ebx

+    pop     ecx

+    ret

+

+ClearScreen:

+    push    eax

+    push    ecx

+    

+    mov     al, ' '

+    mov     ah, 0ch

+    mov     edi, 0b8000h

+    mov     ecx, 80 * 24

+@@:

+    mov     word ptr [edi], ax

+    add     edi, 2

+    loop    @b

+    mov     edi, 0b8000h

+    

+    pop     ecx

+    pop     eax

+

+    ret                

+        

+A2C:

+    and     al, 0fh

+    add     al, '0'

+    cmp     al, '9'

+    jle     @f

+    add     al, 7

+@@:

+    ret

+        

+String1           db  "*** INT ",0

+

+Int0String        db  "00h Divide by 0 -",0

+Int1String        db  "01h Debug exception -",0

+Int2String        db  "02h NMI -",0

+Int3String        db  "03h Breakpoint -",0

+Int4String        db  "04h Overflow -",0

+Int5String        db  "05h Bound -",0

+Int6String        db  "06h Invalid opcode -",0

+Int7String        db  "07h Device not available -",0

+Int8String        db  "08h Double fault -",0

+Int9String        db  "09h Coprocessor seg overrun (reserved) -",0

+Int10String       db  "0Ah Invalid TSS -",0

+Int11String       db  "0Bh Segment not present -",0

+Int12String       db  "0Ch Stack fault -",0

+Int13String       db  "0Dh General protection fault -",0

+Int14String       db  "0Eh Page fault -",0

+Int15String       db  "0Fh (Intel reserved) -",0

+Int16String       db  "10h Floating point error -",0

+Int17String       db  "11h Alignment check -",0

+Int18String       db  "12h Machine check -",0

+Int19String       db  "13h SIMD Floating-Point Exception -",0

+IntUnknownString  db  "??h Unknown interrupt -",0

+

+StringTable       dq  offset Int0String, offset Int1String, offset Int2String, offset Int3String, 

+                      offset Int4String, offset Int5String, offset Int6String, offset Int7String,

+                      offset Int8String, offset Int9String, offset Int10String, offset Int11String,

+                      offset Int12String, offset Int13String, offset Int14String, offset Int15String,

+                      offset Int16String, offset Int17String, offset Int18String, offset Int19String

+

+String2           db  " HALT!! *** (",0

+String3           db  ")",0

+StringRax         db  "RAX=",0

+StringRcx         db  " RCX=",0

+StringRdx         db  " RDX=",0

+StringRbx         db  "RBX=",0

+StringRsp         db  " RSP=",0

+StringRbp         db  " RBP=",0

+StringRsi         db  "RSI=",0

+StringRdi         db  " RDI=",0

+StringEcode       db  " ECODE=",0

+StringR8          db  "R8 =",0

+StringR9          db  " R9 =",0

+StringR10         db  " R10=",0

+StringR11         db  "R11=",0

+StringR12         db  " R12=",0

+StringR13         db  " R13=",0

+StringR14         db  "R14=",0

+StringR15         db  " R15=",0

+StringSs          db  " SS =",0

+StringRflags      db  "RFLAGS=",0

+

+Idtr        df  0

+            df  0

+

+    org 21ffeh

+BlockSignature:

+    dw      0aa55h

+    

+    end

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.S b/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.S
new file mode 100644
index 0000000..8eadd28
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.S
@@ -0,0 +1,1142 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    st16_64.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                        BLOCK_SIZE, 0x0200

+.equ                        BLOCK_MASK, 0x01ff

+.equ                        BLOCK_SHIFT, 9

+

+       .org 0x0

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:              .ascii   "INTEL   "       # OemId               - 8 bytes

+

+SectorSize:         .word  0                  # Sector Size         - 16 bits

+SectorsPerCluster:  .byte  0                  # Sector Per Cluster  - 8 bits

+ReservedSectors:    .word  0                  # Reserved Sectors    - 16 bits

+NoFats:             .byte  0                  # Number of FATs      - 8 bits

+RootEntries:        .word  0                  # Root Entries        - 16 bits

+Sectors:            .word  0                  # Number of Sectors   - 16 bits

+Media:              .byte  0                  # Media               - 8 bits  - ignored

+SectorsPerFat:      .word  0                  # Sectors Per FAT     - 16 bits

+SectorsPerTrack:    .word  0                  # Sectors Per Track   - 16 bits - ignored

+Heads:              .word  0                  # Heads               - 16 bits - ignored

+HiddenSectors:      .long  0                  # Hidden Sectors      - 32 bits - ignored

+LargeSectors:       .long  0                  # Large Sectors       - 32 bits 

+PhysicalDrive:      .byte  0                  # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:        .byte  0                  # Current Head        - 8 bits

+Signature:          .byte  0                  # Signature           - 8 bits  - ignored

+VolId:              .ascii "    "             # Volume Serial Number- 4 bytes

+FatLabel:           .ascii "           "      # Label               - 11 bytes

+SystemId:           .ascii "FAT16   "         # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+      # ASSUME  ds:@code

+      # ASSUME  ss:@code

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00,%bp

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900,%ax

+        movw    %ax,%es

+        testw   %dx,%dx

+        jnz     CheckVarStoreSize

+

+        movb    $1,%al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:(4)

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx,%di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2,%al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0,%al

+        movb    %al, %es:(4)

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di,%di

+        pushw   %es

+        movw    $0x1500,%ax

+        movw    %ax,%es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:(0)                    # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:(2)

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di,%di                             # di = 0

+        movw    $0x2000,%ax

+        movw    %ax,%es

+        call    ReadFile

+        movw    %cs,%ax

+        movw    %ax, %cs:JumpSegment

+

+CheckEm64T: 

+        movl $0x80000001,%eax

+#        cpuid

+        .word 0xA20F

+        btl  $29,%edx

+        jc   CheckEm64TPass

+        pushw %cs

+        popw %ds

+        leaw Em64String,%si

+        movw $18,%cx

+        jmp  PrintStringAndHalt

+CheckEm64TPass: 

+JumpFarInstruction: 

+        .byte 0xea

+JumpOffset: 

+        .word 0x200

+JumpSegment: 

+        .word 0x2000

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1,%si                              # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff,%dx                          # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx,%ax                             # ax = ClusterNumber    

+        andw    $0xfff8,%ax                         # ax = ax & 0xfff8

+        cmpw    $0xfff8,%ax                         # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx,%ax                             # ax = ClusterNumber

+        shlw    %ax                                 # FatOffset = ClusterNumber * 2

+        pushw   %si                                 # Save si

+        movw    %ax,%si                             # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK

+        cmpw    %dx,%ax                             # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2,%bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax,%dx                             # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx,%ax                             # ax = ClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx,%bx                             # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        subw    $2,%ax                              # ax = StartCluster - 2

+        xorb    %bh,%bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si,%ax                             # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax,%bx                             # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1,%si                              # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax   # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax,%esi                           # esi = Start LBA

+        movw    %bx,%cx                             # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc,%bp                         # bp = 0x7bfc

+        movl    %esi,%eax                           # eax = Start LBA

+        xorl    %edx,%edx                           # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx,%bx                             # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx,%cx                             # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx,%bx                             # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es,%ax                             # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax               # ax = Number of blocks into mem system

+        andw    $0x7f,%ax                           # ax = Number of blocks into current seg

+        addw    %bx,%ax                             # ax = End Block number of transfer

+        cmpw    $0x80,%ax                           # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80,%ax                           # ax = Number of blocks past 64K boundry

+        subw    %ax,%bx                             # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl,%cl                             # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx,%dx                             # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl,%dh                             # dh = Head

+        movw    $0x7c00,%bp                         # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al,%ch                             # ch = Cylinder

+        movb    %bl,%al                             # al = Blocks

+        movb    $2,%ah                              # ah = Function 2

+        movw    %di,%bx                             # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx,%ebx

+        addl    %ebx,%esi                           # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx,%cx                             # Blocks = Blocks - NumberOfBlocks

+        movw    %es,%ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx,%ax

+        movw    %ax,%es                             # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0,%cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString,%si

+        movw $7,%cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800,%ax

+        movw %ax,%es

+        movw $160,%di

+        rep

+        movsw

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c

+

+        .org     0x01fa

+LBAOffsetForBootSector: 

+        .long 0x0

+

+        .org    0x01fe

+        .word 0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT, 0x0ed # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT, 0x060 # 8042 control port     

+.equ                 KBD_STATUS_PORT, 0x064 # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD, 0x0df # 8042 command to enable A20

+

+        .org     0x200

+        jmp start

+Em64String: 

+.byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs,%ax

+        movw %ax,%ds

+        movw %ax,%es

+        movw %ax,%ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0,%ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820,%eax

+        movl $20,%ecx

+        movl $0x534d4150, %edx  # SMAP

+        int $0x15

+        jc  MemMapDone

+        addl $20,%edi

+        cmpl $0,%ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax,%edi                      # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx,%ebx

+        movw    %cs,%bx                     # BX=segment

+        shll    $4,%ebx                     # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, (gdtr + 2)            # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, (idtr + 2)            # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401,%ax                    # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25,%cx                     # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loop    Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+    leal OffsetIn32BitProtectedMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetIn32BitProtectedMode 

+

+    leal OffsetInLongMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetInLongMode 

+

+    #

+    # load GDT

+    #

+    .byte 0x66

+    lgdt    gdtr

+

+    #

+    # Enable Protect Mode (set CR0.PE=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    orl   $0x1,%eax       # Set PE=1

+    movl  %eax, %cr0      # Write CR0.

+    .byte 0x66

+    .byte 0xea                        # jmp far 16:32

+OffsetIn32BitProtectedMode: 

+    .long 0x0000000                   # offset $+8   (In32BitProtectedMode)

+    .word 0x10                        # selector  (flat CS)

+In32BitProtectedMode: 

+

+#

+# Entering Long Mode

+#

+    .byte 0x66

+    movw $8,%ax

+    movw %ax,%ds

+    movw %ax,%es

+    movw %ax,%ss

+

+    #

+    # Enable the 64-bit page-translation-table entries by

+    # setting CR4.PAE=1 (this is _required_ before activating

+    # long mode). Paging is not enabled until after long mode

+    # is enabled.

+    #

+    .byte 0xf

+    .byte 0x20

+    .byte 0xe0

+#    mov eax, cr4

+    btsl $5,%eax

+    .byte 0xf

+    .byte 0x22

+    .byte 0xe0

+#    mov cr4, eax

+

+    #

+    # This is the Trapolean Page Tables that are guarenteed

+    #  under 4GB.

+    #

+    # Address Map:

+    #    10000 ~    12000 - efildr (loaded)

+    #    20000 ~    21000 - start64.com

+    #    21000 ~    22000 - efi64.com

+    #    22000 ~    90000 - efildr

+    #    90000 ~    96000 - 4G pagetable (will be reload later)

+    #

+    .byte 0xb8

+    .long 0x90000

+#    mov eax, 90000h

+    movl %eax, %cr3

+

+    #

+    # Enable long mode (set EFER.LME=1).

+    #

+    .byte 0xb9

+    .long 0xc0000080

+#    mov   ecx, 0c0000080h ; EFER MSR number.

+    .byte 0xf

+    .byte 0x32

+#    rdmsr                 ; Read EFER.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x8

+#    bts   eax, 8          ; Set LME=1.

+    .byte 0xf

+    .byte 0x30

+#    wrmsr                 ; Write EFER.

+

+    #

+    # Enable paging to activate long mode (set CR0.PG=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x1f

+#    bts   eax, 31         ; Set PG=1.

+    movl  %eax, %cr0      # Write CR0.

+    jmp   GoToLongMode

+GoToLongMode: 

+

+    .byte 0x67

+    .byte 0xea                  # Far Jump $+9:Selector to reload CS

+OffsetInLongMode: 

+    .long 00000000              #   $+9 Offset is ensuing instruction boundary

+    .word 0x38                  #   Selector is our code selector, 38h

+

+InLongMode: 

+    .byte 0x66

+    movw    $0x30,%ax

+    movw    %ax,%ds

+

+    .byte 0x66

+    movw    $0x18,%ax

+    movw    %ax,%es

+    movw    %ax,%ss

+    movw    %ax,%ds

+

+    .byte 0xbd

+    .long 0x400000

+#    mov ebp,000400000h                  ; Destination of EFILDR32

+    .byte 0xbb

+    .long 0x70000

+#    mov ebx,000070000h                  ; Length of copy

+

+    #

+    # load idt later

+    #

+    .byte 0x48

+    .byte 0x33

+    .byte 0xc0

+#    xor rax, rax

+    .byte 0x66

+     movw $idtr, %ax

+    .byte 0x48

+    .byte 0x5

+    .long 0x20000

+#    add rax, 20000h

+

+    .byte 0xf

+    .byte 0x1

+    .byte 0x18

+#    lidt    fword ptr [rax]

+

+    .byte 0x48

+    .byte 0xc7

+    .byte 0xc0

+    .long 0x21000

+#   mov rax, 21000h

+    .byte 0x50

+#   push rax

+

+# ret

+    .byte 0xc3

+

+Empty8042InputBuffer: 

+        movw $0,%cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2,%al                    # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+        gdtr:    .long  GDT_END - GDT_BASE - 1  # GDT limit 

+        .long 0                     # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE    # Selector [0x0]

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE  # Selector [0x8]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE # Selector [0x18]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE # Selector [0x20]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE  # Selector [0x28]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+#

+# system data segment descriptor

+#

+.equ              SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xCF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+#

+# system code segment descriptor

+#

+.equ              SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xAF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE    # Selector [0x40]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:   .long  IDT_END - IDT_BASE - 1 # IDT limit

+        .quad 0                     # (IDT base gets set above)

+

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid TSS (INT 0ah)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# segment not present (INT 0bh)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# stack fault (INT 0ch)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# general protection (INT 0dh)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# page fault (INT 0eh)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Intel reserved - do not use (INT 0fh)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# floating point error (INT 10h)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# alignment check (INT 11h)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# machine check (INT 12h)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# SIMD floating-point exception (INT 13h)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        .fill 85 * 16, 1, 0   # db (85 * 16) dup(0)

+

+# IRQ 0 (System timer) - (INT 68h)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 1 (8042 Keyboard controller) - (INT 69h)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 3 (COM 2) - (INT 6bh)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 4 (COM 1) - (INT 6ch)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 5 (LPT 2) - (INT 6dh)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 6 (Floppy controller) - (INT 6eh)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 7 (LPT 1) - (INT 6fh)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 8 (RTC Alarm) - (INT 70h)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 9 - (INT 71h)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 10 - (INT 72h)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 11 - (INT 73h)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 12 (PS/2 mouse) - (INT 74h)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 13 (Floating point error) - (INT 75h)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 14 (Secondary IDE) - (INT 76h)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 15 (Primary IDE) - (INT 77h)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.asm b/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.asm
new file mode 100644
index 0000000..93a73d4
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/st16_64.asm
@@ -0,0 +1,1140 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    st16_64.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+VolId             db  "    "        ; Volume Serial Number- 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT16   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+

+CheckEm64T:

+        mov  eax, 080000001h

+;        cpuid

+        dw   0A20Fh

+        bt   edx, 29

+        jc   CheckEm64TPass

+        push cs

+        pop  ds

+        lea  si, [Em64String]

+        mov  cx, 18

+        jmp  PrintStringAndHalt

+CheckEm64TPass:

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0fff8h                           ; ax = ax & 0xfff8

+        cmp     ax,0fff8h                           ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,1                                ; FatOffset = ClusterNumber * 2

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+    lea eax, OffsetIn32BitProtectedMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetIn32BitProtectedMode], eax

+

+    lea eax, OffsetInLongMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetInLongMode], eax

+

+    ;

+    ; load GDT

+    ;

+    db      66h     

+    lgdt    fword ptr [gdtr]

+

+    ;

+    ; Enable Protect Mode (set CR0.PE=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    or    eax, 1h         ; Set PE=1

+    mov   cr0, eax        ; Write CR0.

+    db    066h

+    db    0eah                        ; jmp far 16:32

+OffsetIn32BitProtectedMode:

+    dd    00000000h                   ; offset $+8   (In32BitProtectedMode)

+    dw    10h                         ; selector  (flat CS)

+In32BitProtectedMode:

+

+;

+; Entering Long Mode

+;

+    db   66h

+    mov  ax, 8

+    mov  ds, ax

+    mov  es, ax

+    mov  ss, ax

+

+    ;

+    ; Enable the 64-bit page-translation-table entries by

+    ; setting CR4.PAE=1 (this is _required_ before activating

+    ; long mode). Paging is not enabled until after long mode

+    ; is enabled.

+    ;

+    db 0fh

+    db 20h

+    db 0e0h

+;    mov eax, cr4

+    bts eax, 5

+    db 0fh

+    db 22h

+    db 0e0h

+;    mov cr4, eax

+

+    ;

+    ; This is the Trapolean Page Tables that are guarenteed

+    ;  under 4GB.

+    ;

+    ; Address Map:

+    ;    10000 ~    12000 - efildr (loaded)

+    ;    20000 ~    21000 - start64.com

+    ;    21000 ~    22000 - efi64.com

+    ;    22000 ~    90000 - efildr

+    ;    90000 ~    96000 - 4G pagetable (will be reload later)

+    ;

+    db  0b8h

+    dd  90000h

+;    mov eax, 90000h

+    mov cr3, eax

+

+    ;

+    ; Enable long mode (set EFER.LME=1).

+    ;

+    db  0b9h

+    dd  0c0000080h

+;    mov   ecx, 0c0000080h ; EFER MSR number.

+    db 0fh

+    db 32h

+;    rdmsr                 ; Read EFER.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    08h

+;    bts   eax, 8          ; Set LME=1.

+    db 0fh

+    db 30h

+;    wrmsr                 ; Write EFER.

+

+    ;

+    ; Enable paging to activate long mode (set CR0.PG=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    01fh

+;    bts   eax, 31         ; Set PG=1.

+    mov   cr0, eax        ; Write CR0.

+    jmp   GoToLongMode

+GoToLongMode:

+

+    db      067h

+    db      0eah                ; Far Jump $+9:Selector to reload CS

+OffsetInLongMode:

+    dd      00000000            ;   $+9 Offset is ensuing instruction boundary

+    dw      038h                ;   Selector is our code selector, 38h

+

+InLongMode:

+    db   66h

+    mov     ax, 30h

+    mov     ds, ax

+

+    db   66h

+    mov     ax, 18h

+    mov     es, ax

+    mov     ss, ax

+    mov     ds, ax

+

+    db 0bdh

+    dd 400000h

+;    mov ebp,000400000h                  ; Destination of EFILDR32

+    db 0bbh

+    dd 70000h

+;    mov ebx,000070000h                  ; Length of copy

+

+    ;

+    ; load idt later

+    ;

+    db 48h

+    db 33h

+    db 0c0h

+;    xor rax, rax

+    db 66h

+    mov ax, offset idtr

+    db 48h

+    db 05h

+    dd 20000h

+;    add rax, 20000h

+

+    db 0fh

+    db 01h

+    db 18h

+;    lidt    fword ptr [rax]

+

+    db 48h

+    db 0c7h

+    db 0c0h

+    dd 21000h

+;   mov rax, 21000h

+    db 50h

+;   push rax

+

+; ret

+    db 0c3h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE          ; Selector [0x0]

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE          ; Selector [0x8]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE          ; Selector [0x10]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE          ; Selector [0x18]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE          ; Selector [0x20]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE          ; Selector [0x28]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+;

+; system data segment descriptor

+;

+SYS_DATA64_SEL    equ $-GDT_BASE          ; Selector [0x30]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0CFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+;

+; system code segment descriptor

+;

+SYS_CODE64_SEL    equ $-GDT_BASE          ; Selector [0x38]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0AFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE            ; Selector [0x40]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dq 0                        ; (IDT base gets set above)

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 16) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.S b/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.S
new file mode 100644
index 0000000..18c53f8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.S
@@ -0,0 +1,1157 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    st32_64.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                        BLOCK_SIZE, 0x0200

+.equ                        BLOCK_MASK, 0x01ff

+.equ                        BLOCK_SHIFT, 9

+

+       .org 0x0

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:               .ascii  "INTEL   "    # OemId                           - 8 bytes

+SectorSize:          .word  0              # Sector Size                     - 2 bytes

+SectorsPerCluster:   .byte  0              # Sector Per Cluster              - 1 byte

+ReservedSectors:     .word  0              # Reserved Sectors                - 2 bytes

+NoFats:              .byte  0              # Number of FATs                  - 1 byte

+RootEntries:         .word  0              # Root Entries                    - 2 bytes

+Sectors:             .word  0              # Number of Sectors               - 2 bytes

+Media:               .byte  0              # Media                           - 1 byte

+SectorsPerFat16:     .word  0              # Sectors Per FAT for FAT12/FAT16 - 2 byte

+SectorsPerTrack:     .word  0              # Sectors Per Track               - 2 bytes

+Heads:               .word  0              # Heads                           - 2 bytes

+HiddenSectors:       .long  0              # Hidden Sectors                  - 4 bytes

+LargeSectors:        .long  0              # Large Sectors                   - 4 bytes

+

+#******************************************************************************

+#

+#The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+#the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+#

+#******************************************************************************

+

+SectorsPerFat32:     .long  0              # Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags:            .word  0              # Mirror Flag                     - 2 bytes

+FSVersion:           .word  0              # File System Version             - 2 bytes

+RootCluster:         .long  0              # 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo:              .word  0              # Sector Number of FSINFO         - 2 bytes

+BkBootSector:        .word  0              # Sector Number of Bk BootSector  - 2 bytes

+Reserved:            .fill 12,1,0          # Reserved Field                  - 12 bytes

+PhysicalDrive:       .byte  0              # Physical Drive Number           - 1 byte

+Reserved1:           .byte  0              # Reserved Field                  - 1 byte

+Signature:           .byte  0              # Extended Boot Signature         - 1 byte

+VolId:               .ascii  "    "        # Volume Serial Number            - 4 bytes

+FatLabel:            .ascii  "           " # Volume Label                    - 11 bytes

+FileSystemType:      .ascii  "FAT32   "    # File System Type                - 8 bytes

+

+

+BootSectorEntryPoint: 

+      # ASSUME  ds:@code

+      # ASSUME  ss:@code

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00,%bp

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900,%ax

+        movw    %ax,%es

+        testw   %dx,%dx

+        jnz     CheckVarStoreSize

+

+        movb    $1,%al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:(4)

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx,%di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2,%al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0,%al

+        movb    %al, %es:(4)

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di,%di

+        pushw   %es

+        movw    $0x1500,%ax

+        movw    %ax,%es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:(0)                    # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:(2)

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di,%di                             # di = 0

+        movw    $0x2000,%ax

+        movw    %ax,%es

+        call    ReadFile

+        movw    %cs,%ax

+        movw    %ax, %cs:JumpSegment

+

+CheckEm64T: 

+        movl $0x80000001,%eax

+#        cpuid

+        .word 0xA20F

+        btl  $29,%edx

+        jc   CheckEm64TPass

+        pushw %cs

+        popw %ds

+        leaw Em64String,%si

+        movw $18,%cx

+        jmp  PrintStringAndHalt

+CheckEm64TPass: 

+JumpFarInstruction: 

+        .byte 0xea

+JumpOffset: 

+        .word 0x200

+JumpSegment: 

+        .word 0x2000

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1,%si                              # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff,%dx                          # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx,%ax                             # ax = ClusterNumber    

+        andw    $0xfff8,%ax                         # ax = ax & 0xfff8

+        cmpw    $0xfff8,%ax                         # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx,%ax                             # ax = ClusterNumber

+        shlw    $2, %ax                             # FatOffset = ClusterNumber * 2

+        pushw   %si                                 # Save si

+        movw    %ax,%si                             # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK

+        cmpw    %dx,%ax                             # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2,%bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax,%dx                             # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx,%ax                             # ax = ClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx,%bx                             # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        subw    $2,%ax                              # ax = StartCluster - 2

+        xorb    %bh,%bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si,%ax                             # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax,%bx                             # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1,%si                              # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax   # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax,%esi                           # esi = Start LBA

+        movw    %bx,%cx                             # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc,%bp                         # bp = 0x7bfc

+        movl    %esi,%eax                           # eax = Start LBA

+        xorl    %edx,%edx                           # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx,%bx                             # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx,%cx                             # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx,%bx                             # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es,%ax                             # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax               # ax = Number of blocks into mem system

+        andw    $0x7f,%ax                           # ax = Number of blocks into current seg

+        addw    %bx,%ax                             # ax = End Block number of transfer

+        cmpw    $0x80,%ax                           # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80,%ax                           # ax = Number of blocks past 64K boundry

+        subw    %ax,%bx                             # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl,%cl                             # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx,%dx                             # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl,%dh                             # dh = Head

+        movw    $0x7c00,%bp                         # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al,%ch                             # ch = Cylinder

+        movb    %bl,%al                             # al = Blocks

+        movb    $2,%ah                              # ah = Function 2

+        movw    %di,%bx                             # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx,%ebx

+        addl    %ebx,%esi                           # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx,%cx                             # Blocks = Blocks - NumberOfBlocks

+        movw    %es,%ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx,%ax

+        movw    %ax,%es                             # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0,%cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString,%si

+        movw $7,%cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800,%ax

+        movw %ax,%es

+        movw $160,%di

+        rep

+        movsw

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c

+

+        .org     0x01fa

+LBAOffsetForBootSector: 

+        .long 0x0

+

+        .org    0x01fe

+        .word 0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT, 0x0ed # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT, 0x060 # 8042 control port     

+.equ                 KBD_STATUS_PORT, 0x064 # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD, 0x0d1 # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD, 0x0df # 8042 command to enable A20

+

+        .org     0x200

+        jmp start

+Em64String: 

+.byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs,%ax

+        movw %ax,%ds

+        movw %ax,%es

+        movw %ax,%ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0,%ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820,%eax

+        movl $20,%ecx

+        movl $0x534d4150, %edx  # SMAP

+        int $0x15

+        jc  MemMapDone

+        addl $20,%edi

+        cmpl $0,%ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax,%edi                      # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx,%ebx

+        movw    %cs,%bx                     # BX=segment

+        shll    $4,%ebx                     # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, (gdtr + 2)            # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, (idtr + 2)            # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401,%ax                    # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25,%cx                     # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loop    Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+    leal OffsetIn32BitProtectedMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetIn32BitProtectedMode 

+

+    leal OffsetInLongMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetInLongMode 

+

+    #

+    # load GDT

+    #

+    .byte 0x66

+    lgdt    gdtr

+

+    #

+    # Enable Protect Mode (set CR0.PE=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    orl   $0x1,%eax       # Set PE=1

+    movl  %eax, %cr0      # Write CR0.

+    .byte 0x66

+    .byte 0xea                        # jmp far 16:32

+OffsetIn32BitProtectedMode: 

+    .long 0x0000000                   # offset $+8   (In32BitProtectedMode)

+    .word 0x10                        # selector  (flat CS)

+In32BitProtectedMode: 

+

+#

+# Entering Long Mode

+#

+    .byte 0x66

+    movw $8,%ax

+    movw %ax,%ds

+    movw %ax,%es

+    movw %ax,%ss

+

+    #

+    # Enable the 64-bit page-translation-table entries by

+    # setting CR4.PAE=1 (this is _required_ before activating

+    # long mode). Paging is not enabled until after long mode

+    # is enabled.

+    #

+    .byte 0xf

+    .byte 0x20

+    .byte 0xe0

+#    mov eax, cr4

+    btsl $5,%eax

+    .byte 0xf

+    .byte 0x22

+    .byte 0xe0

+#    mov cr4, eax

+

+    #

+    # This is the Trapolean Page Tables that are guarenteed

+    #  under 4GB.

+    #

+    # Address Map:

+    #    10000 ~    12000 - efildr (loaded)

+    #    20000 ~    21000 - start64.com

+    #    21000 ~    22000 - efi64.com

+    #    22000 ~    90000 - efildr

+    #    90000 ~    96000 - 4G pagetable (will be reload later)

+    #

+    .byte 0xb8

+    .long 0x90000

+#    mov eax, 90000h

+    movl %eax, %cr3

+

+    #

+    # Enable long mode (set EFER.LME=1).

+    #

+    .byte 0xb9

+    .long 0xc0000080

+#    mov   ecx, 0c0000080h ; EFER MSR number.

+    .byte 0xf

+    .byte 0x32

+#    rdmsr                 ; Read EFER.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x8

+#    bts   eax, 8          ; Set LME=1.

+    .byte 0xf

+    .byte 0x30

+#    wrmsr                 ; Write EFER.

+

+    #

+    # Enable paging to activate long mode (set CR0.PG=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x1f

+#    bts   eax, 31         ; Set PG=1.

+    movl  %eax, %cr0      # Write CR0.

+    jmp   GoToLongMode

+GoToLongMode: 

+

+    .byte 0x67

+    .byte 0xea                  # Far Jump $+9:Selector to reload CS

+OffsetInLongMode: 

+    .long 00000000              #   $+9 Offset is ensuing instruction boundary

+    .word 0x38                  #   Selector is our code selector, 38h

+

+InLongMode: 

+    .byte 0x66

+    movw    $0x30,%ax

+    movw    %ax,%ds

+

+    .byte 0x66

+    movw    $0x18,%ax

+    movw    %ax,%es

+    movw    %ax,%ss

+    movw    %ax,%ds

+

+    .byte 0xbd

+    .long 0x400000

+#    mov ebp,000400000h                  ; Destination of EFILDR32

+    .byte 0xbb

+    .long 0x70000

+#    mov ebx,000070000h                  ; Length of copy

+

+    #

+    # load idt later

+    #

+    .byte 0x48

+    .byte 0x33

+    .byte 0xc0

+#    xor rax, rax

+    .byte 0x66

+     movw $idtr, %ax

+    .byte 0x48

+    .byte 0x5

+    .long 0x20000

+#    add rax, 20000h

+

+    .byte 0xf

+    .byte 0x1

+    .byte 0x18

+#    lidt    fword ptr [rax]

+

+    .byte 0x48

+    .byte 0xc7

+    .byte 0xc0

+    .long 0x21000

+#   mov rax, 21000h

+    .byte 0x50

+#   push rax

+

+# ret

+    .byte 0xc3

+

+Empty8042InputBuffer: 

+        movw $0,%cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2,%al                    # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+        gdtr:    .word  GDT_END - GDT_BASE - 1  # GDT limit 

+        .long 0                     # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE    # Selector [0x0]

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE  # Selector [0x8]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE # Selector [0x18]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE # Selector [0x20]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE  # Selector [0x28]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+#

+# system data segment descriptor

+#

+.equ              SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xCF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+#

+# system code segment descriptor

+#

+.equ              SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xAF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE    # Selector [0x40]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:   .long  IDT_END - IDT_BASE - 1 # IDT limit

+        .quad 0                     # (IDT base gets set above)

+

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid TSS (INT 0ah)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# segment not present (INT 0bh)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# stack fault (INT 0ch)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# general protection (INT 0dh)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# page fault (INT 0eh)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Intel reserved - do not use (INT 0fh)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# floating point error (INT 10h)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# alignment check (INT 11h)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# machine check (INT 12h)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# SIMD floating-point exception (INT 13h)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        .fill 85 * 16, 1, 0   # db (85 * 16) dup(0)

+

+# IRQ 0 (System timer) - (INT 68h)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 1 (8042 Keyboard controller) - (INT 69h)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 3 (COM 2) - (INT 6bh)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 4 (COM 1) - (INT 6ch)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 5 (LPT 2) - (INT 6dh)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 6 (Floppy controller) - (INT 6eh)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 7 (LPT 1) - (INT 6fh)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 8 (RTC Alarm) - (INT 70h)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 9 - (INT 71h)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 10 - (INT 72h)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 11 - (INT 73h)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 12 (PS/2 mouse) - (INT 74h)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 13 (Floating point error) - (INT 75h)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 14 (Secondary IDE) - (INT 76h)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 15 (Primary IDE) - (INT 77h)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.asm b/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.asm
new file mode 100644
index 0000000..9761dc8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/st32_64.asm
@@ -0,0 +1,1156 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    st32_64.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId               db  "INTEL   "    ; OemId                           - 8 bytes

+SectorSize          dw  0             ; Sector Size                     - 2 bytes

+SectorsPerCluster   db  0             ; Sector Per Cluster              - 1 byte

+ReservedSectors     dw  0             ; Reserved Sectors                - 2 bytes

+NoFats              db  0             ; Number of FATs                  - 1 byte

+RootEntries         dw  0             ; Root Entries                    - 2 bytes

+Sectors             dw  0             ; Number of Sectors               - 2 bytes

+Media               db  0             ; Media                           - 1 byte

+SectorsPerFat16     dw  0             ; Sectors Per FAT for FAT12/FAT16 - 2 byte

+SectorsPerTrack     dw  0             ; Sectors Per Track               - 2 bytes

+Heads               dw  0             ; Heads                           - 2 bytes

+HiddenSectors       dd  0             ; Hidden Sectors                  - 4 bytes

+LargeSectors        dd  0             ; Large Sectors                   - 4 bytes

+

+;******************************************************************************

+;

+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+;

+;******************************************************************************

+

+SectorsPerFat32     dd  0             ; Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags            dw  0             ; Mirror Flag                     - 2 bytes

+FSVersion           dw  0             ; File System Version             - 2 bytes

+RootCluster         dd  0             ; 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo              dw  0             ; Sector Number of FSINFO         - 2 bytes

+BkBootSector        dw  0             ; Sector Number of Bk BootSector  - 2 bytes

+Reserved            db  12 dup(0)     ; Reserved Field                  - 12 bytes

+PhysicalDrive       db  0             ; Physical Drive Number           - 1 byte

+Reserved1           db  0             ; Reserved Field                  - 1 byte

+Signature           db  0             ; Extended Boot Signature         - 1 byte

+VolId               db  "    "        ; Volume Serial Number            - 4 bytes

+FatLabel            db  "           " ; Volume Label                    - 11 bytes

+FileSystemType      db  "FAT32   "    ; File System Type                - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+

+CheckEm64T:

+        mov  eax, 080000001h

+;        cpuid

+        dw   0A20Fh

+        bt   edx, 29

+        jc   CheckEm64TPass

+        push cs

+        pop  ds

+        lea  si, [Em64String]

+        mov  cx, 18

+        jmp  PrintStringAndHalt

+CheckEm64TPass:

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0fff8h                           ; ax = ax & 0xfff8

+        cmp     ax,0fff8h                           ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,2                                ; FatOffset = ClusterNumber * 4

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+    lea eax, OffsetIn32BitProtectedMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetIn32BitProtectedMode], eax

+

+    lea eax, OffsetInLongMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetInLongMode], eax

+

+    ;

+    ; load GDT

+    ;

+    db      66h     

+    lgdt    fword ptr [gdtr]

+

+    ;

+    ; Enable Protect Mode (set CR0.PE=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    or    eax, 1h         ; Set PE=1

+    mov   cr0, eax        ; Write CR0.

+    db    066h

+    db    0eah                        ; jmp far 16:32

+OffsetIn32BitProtectedMode:

+    dd    00000000h                   ; offset $+8   (In32BitProtectedMode)

+    dw    10h                         ; selector  (flat CS)

+In32BitProtectedMode:

+

+;

+; Entering Long Mode

+;

+    db   66h

+    mov  ax, 8

+    mov  ds, ax

+    mov  es, ax

+    mov  ss, ax

+

+    ;

+    ; Enable the 64-bit page-translation-table entries by

+    ; setting CR4.PAE=1 (this is _required_ before activating

+    ; long mode). Paging is not enabled until after long mode

+    ; is enabled.

+    ;

+    db 0fh

+    db 20h

+    db 0e0h

+;    mov eax, cr4

+    bts eax, 5

+    db 0fh

+    db 22h

+    db 0e0h

+;    mov cr4, eax

+

+    ;

+    ; This is the Trapolean Page Tables that are guarenteed

+    ;  under 4GB.

+    ;

+    ; Address Map:

+    ;    10000 ~    12000 - efildr (loaded)

+    ;    20000 ~    21000 - start64.com

+    ;    21000 ~    22000 - efi64.com

+    ;    22000 ~    90000 - efildr

+    ;    90000 ~    96000 - 4G pagetable (will be reload later)

+    ;

+    db  0b8h

+    dd  90000h

+;    mov eax, 90000h

+    mov cr3, eax

+

+    ;

+    ; Enable long mode (set EFER.LME=1).

+    ;

+    db  0b9h

+    dd  0c0000080h

+;    mov   ecx, 0c0000080h ; EFER MSR number.

+    db 0fh

+    db 32h

+;    rdmsr                 ; Read EFER.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    08h

+;    bts   eax, 8          ; Set LME=1.

+    db 0fh

+    db 30h

+;    wrmsr                 ; Write EFER.

+

+    ;

+    ; Enable paging to activate long mode (set CR0.PG=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    01fh

+;    bts   eax, 31         ; Set PG=1.

+    mov   cr0, eax        ; Write CR0.

+    jmp   GoToLongMode

+GoToLongMode:

+

+    db      067h

+    db      0eah                ; Far Jump $+9:Selector to reload CS

+OffsetInLongMode:

+    dd      00000000            ;   $+9 Offset is ensuing instruction boundary

+    dw      038h                ;   Selector is our code selector, 38h

+

+InLongMode:

+    db   66h

+    mov     ax, 30h

+    mov     ds, ax

+

+    db   66h

+    mov     ax, 18h

+    mov     es, ax

+    mov     ss, ax

+    mov     ds, ax

+

+    db 0bdh

+    dd 400000h

+;    mov ebp,000400000h                  ; Destination of EFILDR32

+    db 0bbh

+    dd 70000h

+;    mov ebx,000070000h                  ; Length of copy

+

+    ;

+    ; load idt later

+    ;

+    db 48h

+    db 33h

+    db 0c0h

+;    xor rax, rax

+    db 66h

+    mov ax, offset idtr

+    db 48h

+    db 05h

+    dd 20000h

+;    add rax, 20000h

+

+    db 0fh

+    db 01h

+    db 18h

+;    lidt    fword ptr [rax]

+

+    db 48h

+    db 0c7h

+    db 0c0h

+    dd 21000h

+;   mov rax, 21000h

+    db 50h

+;   push rax

+

+; ret

+    db 0c3h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE          ; Selector [0x0]

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE          ; Selector [0x8]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE          ; Selector [0x10]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE          ; Selector [0x18]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE          ; Selector [0x20]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE          ; Selector [0x28]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+;

+; system data segment descriptor

+;

+SYS_DATA64_SEL    equ $-GDT_BASE          ; Selector [0x30]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0CFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+;

+; system code segment descriptor

+;

+SYS_CODE64_SEL    equ $-GDT_BASE          ; Selector [0x38]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0AFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE            ; Selector [0x40]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dq 0                        ; (IDT base gets set above)

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 16) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start.S b/uefi/linaro-edk2/DuetPkg/BootSector/start.S
new file mode 100644
index 0000000..f96d06e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start.S
@@ -0,0 +1,919 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    start.S

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+        .stack: 

+        .486p: 

+        .code16

+    

+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                        BLOCK_SIZE, 0x0200

+.equ                        BLOCK_MASK, 0x01ff

+.equ                        BLOCK_SHIFT, 9

+

+       .org 0x0

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:              .ascii   "INTEL   "       # OemId               - 8 bytes

+

+SectorSize:         .word  0                  # Sector Size         - 16 bits

+SectorsPerCluster:  .byte  0                  # Sector Per Cluster  - 8 bits

+ReservedSectors:    .word  0                  # Reserved Sectors    - 16 bits

+NoFats:             .byte  0                  # Number of FATs      - 8 bits

+RootEntries:        .word  0                  # Root Entries        - 16 bits

+Sectors:            .word  0                  # Number of Sectors   - 16 bits

+Media:              .byte  0                  # Media               - 8 bits  - ignored

+SectorsPerFat:      .word  0                  # Sectors Per FAT     - 16 bits

+SectorsPerTrack:    .word  0                  # Sectors Per Track   - 16 bits - ignored

+Heads:              .word  0                  # Heads               - 16 bits - ignored

+HiddenSectors:      .long  0                  # Hidden Sectors      - 32 bits - ignored

+LargeSectors:       .long  0                  # Large Sectors       - 32 bits 

+PhysicalDrive:      .byte  0                  # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:        .byte  0                  # Current Head        - 8 bits

+Signature:          .byte  0                  # Signature           - 8 bits  - ignored

+VolId:              .ascii "    "             # Volume Serial Number- 4 bytes

+FatLabel:           .ascii "           "      # Label               - 11 bytes

+SystemId:           .ascii "FAT12   "         # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00, %bp

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900, %ax

+        movw    %ax, %es

+        testw   %dx, %dx

+        jnz     CheckVarStoreSize

+

+        movb    $1, %al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:(4)

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx, %di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2, %al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0, %al

+        movb    %al, %es:(4)

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di, %di

+        pushw   %es

+        movw    $0x1500, %ax

+        movw    %ax, %es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:(0)                    # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:(2)

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di, %di                            # di = 0

+        movw    $0x2000, %ax

+        movw    %ax, %es

+        call    ReadFile

+        movw    %cs, %ax

+        movw    %ax, %cs:JumpSegment

+

+JumpFarInstruction: 

+        .byte   0xea

+JumpOffset: 

+        .word   0x200

+JumpSegment: 

+        .word   0x2000

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1, %si                             # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff, %dx                         # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx, %ax                            # ax = ClusterNumber    

+        andw    $0xff8, %ax                         # ax = ax & 0xff8

+        cmpw    $0xff8, %ax                         # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx, %ax                            # ax = ClusterNumber

+        shlw    %ax                                 # ax = ClusterNumber * 2

+        addw    %cx, %ax                            # ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3

+        shrw    %ax                                 # FatOffset = ClusterNumber*3 / 2

+        pushw   %si                                 # Save si

+        movw    %ax, %si                            # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK,%si                     # si = FatOffset & BLOCK_MASK

+        cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2, %bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax, %dx                            # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx, %ax                            # ax = ClusterNumber

+        andw    $1, %ax                             # See if this is an odd cluster number

+        je      EvenFatEntry

+        shrw    $4, %bx                             # NextClusterNumber = NextClusterNumber >> 4

+EvenFatEntry: 

+        andw    $0xfff, %bx                         # Strip upper 4 bits of NextClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx, %bx                            # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        subw    $2, %ax                             # ax = StartCluster - 2

+        xorb    %bh, %bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si, %ax                            # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax, %bx                            # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1, %si                             # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax   # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax, %esi                          # esi = Start LBA

+        movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc, %bp                        # bp = 0x7bfc

+        movl    %esi, %eax                          # eax = Start LBA

+        xorl    %edx, %edx                          # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx, %bx                            # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es, %ax                            # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax               # ax = Number of blocks into mem system

+        andw    $0x7f, %ax                          # ax = Number of blocks into current seg

+        addw    %bx, %ax                            # ax = End Block number of transfer

+        cmpw    $0x80, %ax                          # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80, %ax                          # ax = Number of blocks past 64K boundry

+        subw    %ax, %bx                            # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx, %dx                            # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl, %dh                            # dh = Head

+        movw    $0x7c00, %bp                        # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al, %ch                            # ch = Cylinder

+        movb    %bl, %al                            # al = Blocks

+        movb    $2, %ah                             # ah = Function 2

+        movw    %di, %bx                            # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx, %ebx

+        addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+        movw    %es, %ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx, %ax

+        movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0, %cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString, %si

+        movw $7, %cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800, %ax

+        movw %ax, %es

+        movw $160, %di

+        rep

+        movsw

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c

+

+        .org     0x01fa

+LBAOffsetForBootSector: 

+        .long   0x0

+

+        .org    0x01fe

+        .word   0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT, 0x0ed           # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT, 0x060     # 8042 control port     

+.equ                 KBD_STATUS_PORT, 0x064      # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD, 0x0d1  # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD, 0x0df       # 8042 command to enable A20

+

+        .org     0x200

+        jmp start

+Em64String: 

+        .byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs, %ax

+        movw %ax, %ds

+        movw %ax, %es

+        movw %ax, %ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0, %ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820, %eax

+        movl $20, %ecx

+        movl $0x534d4150, %edx  # SMAP

+        int $0x15

+        jc  MemMapDone

+        addl $20, %edi

+        cmpl $0, %ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax, %edi                     # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx, %ebx

+        movw    %cs, %bx                    # BX=segment

+        shll    $4, %ebx                    # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, (gdtr + 2)            # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, (idtr + 2)            # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+        addl $0x1000, %ebx                  # Source of EFI32

+        movl %ebx, JUMP+2

+        addl $0x1000, %ebx

+        movl %ebx, %esi                     # Source of EFILDR32

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401, %ax                   # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        mov     $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        out     %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        mov     $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        out     %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25, %cx                    # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loop    Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+        movw    $0x0008, %bx                # Flat data descriptor

+

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+        .byte   0x66

+        lgdt    gdtr

+        .byte   0x66

+        lidt    idtr

+

+        movl    %cr0, %eax

+        orb     $1, %al

+        movl    %eax, %cr0

+JUMP: 

+# jmp far 0010:00020000

+        .byte 0x66

+        .byte 0xea

+        .long 0x00020000

+        .word 0x0010

+

+Empty8042InputBuffer: 

+        movw $0, %cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        in      $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2, %al                   # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+        gdtr:    .long  GDT_END - GDT_BASE - 1  # GDT limit 

+        .long 0                                 # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE5_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:  .long  IDT_END - IDT_BASE - 1 # IDT limit

+        .long 0                      # (IDT base gets set above)

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+         .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# invalid TSS (INT 0x0a)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# segment not present (INT 0x0b)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# stack fault (INT 0x0c)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# general protection (INT 0x0d)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# page fault (INT 0x0e)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Intel reserved - do not use (INT 0x0f)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# floating point error (INT 0x10)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# alignment check (INT 0x11)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# machine check (INT 0x12)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# SIMD floating-point exception (INT 0x13)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+    .fill 85 * 8, 1, 0   # db (85 * 8) dup(0)

+

+# IRQ 0 (System timer) - (INT 0x68)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 1 (8042 Keyboard controller) - (INT 0x69)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 0x6a)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 3 (COM 2) - (INT 0x6b)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 4 (COM 1) - (INT 0x6c)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 5 (LPT 2) - (INT 0x6d)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 6 (Floppy controller) - (INT 0x6e)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 7 (LPT 1) - (INT 0x6f)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 8 (RTC Alarm) - (INT 0x70)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 9 - (INT 0x71)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 10 - (INT 0x72)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 11 - (INT 0x73)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 12 (PS/2 mouse) - (INT 0x74)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+        

+# IRQ 13 (Floating point error) - (INT 0x75)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 14 (Secondary IDE) - (INT 0x76)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 15 (Primary IDE) - (INT 0x77)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .long SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e |  0x80 # (10001110)type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start.asm b/uefi/linaro-edk2/DuetPkg/BootSector/start.asm
new file mode 100644
index 0000000..9cc05ff
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start.asm
@@ -0,0 +1,916 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    start.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+VolId             db  "    "        ; Volume Serial Number- 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT12   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0ff8h                            ; ax = ax & 0xff8

+        cmp     ax,0ff8h                            ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,1                                ; ax = ClusterNumber * 2

+        add     ax,cx                               ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3

+        shr     ax,1                                ; FatOffset = ClusterNumber*3 / 2

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        and     ax,1                                ; See if this is an odd cluster number

+        je      EvenFatEntry

+        shr     bx,4                                ; NextClusterNumber = NextClusterNumber >> 4

+EvenFatEntry:

+        and     bx,0fffh                            ; Strip upper 4 bits of NextClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+        add ebx,01000h                      ; Source of EFI32

+        mov dword ptr [JUMP+2],ebx

+        add ebx,01000h

+        mov esi,ebx                         ; Source of EFILDR32

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+        mov     bx,0008h                    ; Flat data descriptor

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+        db      66h     

+        lgdt    fword ptr [gdtr]

+        db      66h     

+        lidt    fword ptr [idtr]

+

+        mov     eax,cr0

+        or      al,1

+        mov     cr0,eax

+JUMP:

+; jmp far 0010:00020000

+        db  066h

+        db  0eah

+        dd  000020000h

+        dw  00010h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE5_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dd 0                        ; (IDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 8) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start16.S b/uefi/linaro-edk2/DuetPkg/BootSector/start16.S
new file mode 100644
index 0000000..a4cb151
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start16.S
@@ -0,0 +1,910 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    start16.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+        #.MODEL small

+        .stack: 

+        .486p: 

+        .code16 

+

+.equ                        FAT_DIRECTORY_ENTRY_SIZE,   0x0020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT,  5

+.equ                        BLOCK_SIZE,                 0x0200

+.equ                        BLOCK_MASK,                 0x01ff

+.equ                        BLOCK_SHIFT,                9

+

+        .org 0x00

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:             .ascii  "INTEL   "    # OemId               - 8 bytes

+

+SectorSize:        .word  0              # Sector Size         - 16 bits

+SectorsPerCluster: .byte  0              # Sector Per Cluster  - 8 bits

+ReservedSectors:   .word  0              # Reserved Sectors    - 16 bits

+NoFats:            .byte  0              # Number of FATs      - 8 bits

+RootEntries:       .word  0              # Root Entries        - 16 bits

+Sectors:           .word  0              # Number of Sectors   - 16 bits

+Media:             .byte  0              # Media               - 8 bits  - ignored

+SectorsPerFat:     .word  0              # Sectors Per FAT     - 16 bits

+SectorsPerTrack:   .word  0              # Sectors Per Track   - 16 bits - ignored

+Heads:             .word  0              # Heads               - 16 bits - ignored

+HiddenSectors:     .long  0              # Hidden Sectors      - 32 bits - ignored

+LargeSectors:      .long  0              # Large Sectors       - 32 bits 

+PhysicalDrive:     .byte  0              # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:       .byte  0              # Current Head        - 8 bits

+Signature:         .byte  0              # Signature           - 8 bits  - ignored

+VolId:             .ascii  "    "        # Volume Serial Number- 4 bytes

+FatLabel:          .ascii  "           " # Label               - 11 bytes

+SystemId:          .ascii  "FAT16   "    # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00, %bp

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900, %ax

+        movw    %ax, %es

+        testw   %dx, %dx

+        jnz     CheckVarStoreSize

+

+        movb    $1, %al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:4

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx, %di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2, %al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0, %al

+        movb    %al, %es:4

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di, %di

+        pushw   %es

+        movw    $0x1500, %ax

+        movw    %ax, %es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:0                      # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:2

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di, %di                            # di = 0

+        movw    $0x2000, %ax

+        movw    %ax, %es

+        call    ReadFile

+        movw    %cs, %ax

+        movw    %ax, %cs:JumpSegment

+

+JumpFarInstruction: 

+        .byte   0xea

+JumpOffset: 

+        .word   0x200

+JumpSegment: 

+        .word   0x2000

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1, %si                             # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff, %dx                         # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx, %ax                            # ax = ClusterNumber    

+        andw    $0xfff8, %ax                        # ax = ax & 0xfff8

+        cmpw    $0xfff8, %ax                        # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx, %ax                            # ax = ClusterNumber

+        shlw    %ax                                 # FatOffset = ClusterNumber * 2

+        pushw   %si                                 # Save si

+        movw    %ax, %si                            # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK

+        cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2, %bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax, %dx                            # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx, %ax                            # ax = ClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx, %bx                            # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        subw    $2, %ax                             # ax = StartCluster - 2

+        xorb    %bh, %bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si, %ax                            # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax, %bx                            # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1, %si                             # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax, %esi                          # esi = Start LBA

+        movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc, %bp                        # bp = 0x7bfc

+        movl    %esi, %eax                          # eax = Start LBA

+        xorl    %edx, %edx                          # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx, %bx                            # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es, %ax                            # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax               # ax = Number of blocks into mem system

+        andw    $0x7f, %ax                          # ax = Number of blocks into current seg

+        addw    %bx, %ax                            # ax = End Block number of transfer

+        cmpw    $0x80, %ax                          # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80, %ax                          # ax = Number of blocks past 64K boundry

+        subw    %ax, %bx                            # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx, %dx                            # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl, %dh                            # dh = Head

+        movw    $0x7c00, %bp                        # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al, %ch                            # ch = Cylinder

+        movb    %bl, %al                            # al = Blocks

+        movb    $2, %ah                             # ah = Function 2

+        movw    %di, %bx                            # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx, %ebx

+        addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+        movw    %es, %ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx, %ax

+        movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0, %cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString, %si

+        movw $7, %cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800, %ax

+        movw %ax, %es

+        movw $160, %di

+        rep

+        movsw

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c

+

+        # .org     0x01fa # Just for passing build.

+LBAOffsetForBootSector: 

+        .long   0x0

+

+        # .org     0x01fe # Just for passing build.

+        .word   0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT,            0x0ed     # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT,      0x060     # 8042 control port     

+.equ                 KBD_STATUS_PORT,       0x064     # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD,   0x0d1     # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD,        0x0df     # 8042 command to enable A20

+

+        # .org     0x0200 # Just for passing build.

+        jmp start

+Em64String: 

+        .byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs, %ax

+        movw %ax, %ds

+        movw %ax, %es

+        movw %ax, %ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0, %ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820, %eax

+        movl $20, %ecx

+        movl $0x534d4150, %edx  # 0x534d4150  stands for 'SMAP'

+        int $0x15

+        jc  MemMapDone

+        addl $20, %edi

+        cmpl $0, %ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax, %edi                     # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx, %ebx

+        movw    %cs, %bx                    # BX=segment

+        shll    $4, %ebx                    # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, gdtr + 2              # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, idtr + 2              # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+        addl $0x1000, %ebx                  # Source of EFI32

+        movl %ebx, JUMP+2

+        addl $0x1000, %ebx

+        movl %ebx, %esi                     # Source of EFILDR32

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401, %ax                   # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25, %cx                    # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loop    Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+        movw    $0x0008, %bx                # Flat data descriptor

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+        .byte   0x66

+        lgdt    gdtr

+        .byte   0x66

+        lidt    idtr

+

+        movl    %cr0, %eax

+        orb     $1, %al

+        movl    %eax, %cr0

+JUMP: 

+# jmp far 0010:00020000

+        .byte 0x66

+        .byte 0xea

+        .long 0x00020000

+        .word 0x0010

+

+Empty8042InputBuffer: 

+        movw $0, %cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2, %al                   # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+gdtr:   .word  GDT_END - GDT_BASE - 1       # GDT limit

+        .long 0                             # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE5_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:   .word IDT_END - IDT_BASE - 1  # IDT limit

+        .long 0                       # (IDT base gets set above)

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# invalid TSS (INT 0ah)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# segment not present (INT 0bh)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# stack fault (INT 0ch)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# general protection (INT 0dh)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# page fault (INT 0eh)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# Intel reserved - do not use (INT 0fh)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# floating point error (INT 10h)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# alignment check (INT 11h)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# machine check (INT 12h)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# SIMD floating-point exception (INT 13h)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        .fill  85 * 8, 1, 0

+

+# IRQ 0 (System timer) - (INT 68h)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 1 (8042 Keyboard controller) - (INT 69h)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 3 (COM 2) - (INT 6bh)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 4 (COM 1) - (INT 6ch)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 5 (LPT 2) - (INT 6dh)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 6 (Floppy controller) - (INT 6eh)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 7 (LPT 1) - (INT 6fh)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 8 (RTC Alarm) - (INT 70h)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 9 - (INT 71h)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 10 - (INT 72h)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 11 - (INT 73h)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 12 (PS/2 mouse) - (INT 74h)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 13 (Floating point error) - (INT 75h)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 14 (Secondary IDE) - (INT 76h)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+# IRQ 15 (Primary IDE) - (INT 77h)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0             # offset 15:0

+        .word SYS_CODE_SEL  # selector 15:0

+        .byte 0             # 0 for interrupt gate

+        .byte 0x0e | 0x80  # (10001110)type = 386 interrupt gate, present

+        .word 0             # offset 31:16

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start16.asm b/uefi/linaro-edk2/DuetPkg/BootSector/start16.asm
new file mode 100644
index 0000000..05d0b2d
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start16.asm
@@ -0,0 +1,909 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    start16.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+VolId             db  "    "        ; Volume Serial Number- 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT16   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0fff8h                           ; ax = ax & 0xfff8

+        cmp     ax,0fff8h                           ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,1                                ; FatOffset = ClusterNumber * 2

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+        add ebx,01000h                      ; Source of EFI32

+        mov dword ptr [JUMP+2],ebx

+        add ebx,01000h

+        mov esi,ebx                         ; Source of EFILDR32

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+        mov     bx,0008h                    ; Flat data descriptor

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+        db      66h     

+        lgdt    fword ptr [gdtr]

+        db      66h     

+        lidt    fword ptr [idtr]

+

+        mov     eax,cr0

+        or      al,1

+        mov     cr0,eax

+JUMP:

+; jmp far 0010:00020000

+        db  066h

+        db  0eah

+        dd  000020000h

+        dw  00010h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE5_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dd 0                        ; (IDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 8) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start32.S b/uefi/linaro-edk2/DuetPkg/BootSector/start32.S
new file mode 100644
index 0000000..dc683f5
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start32.S
@@ -0,0 +1,927 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    start32.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+        #.MODEL small

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                        BLOCK_SIZE, 0x0200

+.equ                        BLOCK_MASK, 0x01ff

+.equ                        BLOCK_SHIFT, 9

+

+        .org 0x0

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:               .ascii  "INTEL   "    # OemId                           - 8 bytes

+SectorSize:          .word  0              # Sector Size                     - 2 bytes

+SectorsPerCluster:   .byte  0              # Sector Per Cluster              - 1 byte

+ReservedSectors:     .word  0              # Reserved Sectors                - 2 bytes

+NoFats:              .byte  0              # Number of FATs                  - 1 byte

+RootEntries:         .word  0              # Root Entries                    - 2 bytes

+Sectors:             .word  0              # Number of Sectors               - 2 bytes

+Media:               .byte  0              # Media                           - 1 byte

+SectorsPerFat16:     .word  0              # Sectors Per FAT for FAT12/FAT16 - 2 byte

+SectorsPerTrack:     .word  0              # Sectors Per Track               - 2 bytes

+Heads:               .word  0              # Heads                           - 2 bytes

+HiddenSectors:       .long  0              # Hidden Sectors                  - 4 bytes

+LargeSectors:        .long  0              # Large Sectors                   - 4 bytes

+

+#******************************************************************************

+#

+#The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+#the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+#

+#******************************************************************************

+

+SectorsPerFat32:     .long  0              # Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags:            .word  0              # Mirror Flag                     - 2 bytes

+FSVersion:           .word  0              # File System Version             - 2 bytes

+RootCluster:         .long  0              # 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo:              .word  0              # Sector Number of FSINFO         - 2 bytes

+BkBootSector:        .word  0              # Sector Number of Bk BootSector  - 2 bytes

+Reserved:            .fill 12,1,0          # Reserved Field                  - 12 bytes

+PhysicalDrive:       .byte  0              # Physical Drive Number           - 1 byte

+Reserved1:           .byte  0              # Reserved Field                  - 1 byte

+Signature:           .byte  0              # Extended Boot Signature         - 1 byte

+VolId:               .ascii  "    "        # Volume Serial Number            - 4 bytes

+FatLabel:            .ascii  "           " # Volume Label                    - 11 bytes

+FileSystemType:      .ascii  "FAT32   "    # File System Type                - 8 bytes

+

+BootSectorEntryPoint: 

+        #ASSUME ds:@code

+        #ASSUME ss:@code

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00, %bp

+

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900, %ax

+        movw    %ax, %es

+        testw   %dx, %dx

+        jnz     CheckVarStoreSize

+

+        movb    $1, %al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:4

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx, %di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2, %al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0, %al

+        movb    %al, %es:4

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di, %di

+        pushw   %es

+        movw    $0x1500, %ax

+        movw    %ax, %es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:0                       # Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:2

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di, %di                            # di = 0

+        movw    $0x2000, %ax

+        movw    %ax, %es

+        call    ReadFile

+        movw    %cs, %ax

+        movw    %ax, %cs:JumpSegment

+JumpFarInstruction: 

+        .byte   0xea

+JumpOffset: 

+        .word   0x200

+JumpSegment: 

+        .word   0x2000

+

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1, %si                             # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff, %dx                         # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx, %ax                            # ax = ClusterNumber    

+        andw    $0xfff8, %ax                        # ax = ax & 0xfff8

+        cmpw    $0xfff8, %ax                        # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx, %ax                            # ax = ClusterNumber

+        shlw    $2, %ax                             # FatOffset = ClusterNumber * 4

+        pushw   %si                                 # Save si

+        movw    %ax, %si                            # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK

+        cmpw    %dx, %ax                            # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2, %bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax, %dx                            # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx, %ax                            # ax = ClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx, %bx                            # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx, %cx                            # ClusterNumber = NextClusterNumber

+        subw    $2, %ax                             # ax = StartCluster - 2

+        xorb    %bh, %bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si, %ax                            # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax, %bx                            # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1, %si                             # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax, %esi                          # esi = Start LBA

+        movw    %bx, %cx                            # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc, %bp                        # bp = 0x7bfc

+        movl    %esi, %eax                          # eax = Start LBA

+        xorl    %edx, %edx                          # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx, %bx                            # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx, %bx                            # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es, %ax                            # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax                # ax = Number of blocks into mem system

+        andw    $0x7f, %ax                          # ax = Number of blocks into current seg

+        addw    %bx, %ax                            # ax = End Block number of transfer

+        cmpw    $0x80, %ax                          # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80, %ax                          # ax = Number of blocks past 64K boundry

+        subw    %ax, %bx                            # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx, %dx                            # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl, %dh                            # dh = Head

+        movw    $0x7c00, %bp                        # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al, %ch                            # ch = Cylinder

+        movb    %bl, %al                            # al = Blocks

+        movb    $2, %ah                             # ah = Function 2

+        movw    %di, %bx                            # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx, %ebx

+        addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks

+        movw    %es, %ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx, %ax

+        movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0, %cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString, %si

+        movw $7, %cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800, %ax

+        movw %ax, %es

+        movw $160, %di

+        rep

+        movsw

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!', 0x0c

+

+        .org     0x01fa

+LBAOffsetForBootSector: 

+        .long   0x0

+

+        .org    0x01fe

+        .word   0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT, 0x0ed           # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT, 0x060     # 8042 control port     

+.equ                 KBD_STATUS_PORT, 0x064      # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD, 0x0d1  # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD, 0x0df       # 8042 command to enable A20

+

+        .org    0x200

+        jmp start

+Em64String: 

+        .byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs, %ax

+        movw %ax, %ds

+        movw %ax, %es

+        movw %ax, %ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0, %ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820, %eax

+        movl $20, %ecx

+        movl $0x534d4150, %edx  # 0x534d4150 = 'SMAP' 

+        int  $0x15

+        jc  MemMapDone

+        addl $20, %edi

+        cmpl $0, %ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax, %edi                     # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx, %ebx

+        movw    %cs, %bx                    # BX=segment

+        shll    $4, %ebx                    # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, gdtr + 2            # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, idtr + 2            # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+        addl $0x1000, %ebx                  # Source of EFI32

+        movl %ebx, JUMP+2

+        addl $0x1000, %ebx

+        movl %ebx, %esi                     # Source of EFILDR32

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401, %ax                   # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25, %cx                    # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loopl   Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+        movw    $0x0008, %bx                # Flat data descriptor

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+        .byte   0x66

+        lgdt    gdtr

+        .byte   0x66

+        lidt    idtr

+

+        movl    %cr0, %eax

+        orb     $1, %al

+        movl    %eax, %cr0

+JUMP: 

+# jmp far 0010:00020000

+        .byte 0x66

+        .byte 0xea

+        .long 0x00020000

+        .word 0x0010

+

+Empty8042InputBuffer: 

+        movw $0, %cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2, %al                   # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+gdtr:    .word GDT_END - GDT_BASE - 1   

+        .long 0                     # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF      # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF      # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF      # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF      # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE5_SEL, .-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:            .word IDT_END - IDT_BASE - 1  

+        .long 0                     # (IDT base gets set above)

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# invalid TSS (INT 0ah)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# segment not present (INT 0bh)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# stack fault (INT 0ch)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# general protection (INT 0dh)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# page fault (INT 0eh)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Intel reserved - do not use (INT 0fh)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# floating point error (INT 10h)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# alignment check (INT 11h)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# machine check (INT 12h)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# SIMD floating-point exception (INT 13h)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        .fill 85 * 8, 1, 0

+

+# IRQ 0 (System timer) - (INT 68h)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 1 (8042 Keyboard controller) - (INT 69h)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 3 (COM 2) - (INT 6bh)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 4 (COM 1) - (INT 6ch)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 5 (LPT 2) - (INT 6dh)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 6 (Floppy controller) - (INT 6eh)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 7 (LPT 1) - (INT 6fh)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 8 (RTC Alarm) - (INT 70h)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 9 - (INT 71h)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 10 - (INT 72h)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 11 - (INT 73h)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 12 (PS/2 mouse) - (INT 74h)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 13 (Floating point error) - (INT 75h)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 14 (Secondary IDE) - (INT 76h)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+# IRQ 15 (Primary IDE) - (INT 77h)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0            # offset 15:0

+        .word SYS_CODE_SEL # selector 15:0

+        .byte 0            # 0 for interrupt gate

+        .byte 0x0e | 0x80  # type = 386 interrupt gate, present

+        .word 0            # offset 31:16

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start32.asm b/uefi/linaro-edk2/DuetPkg/BootSector/start32.asm
new file mode 100644
index 0000000..aaf04b8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start32.asm
@@ -0,0 +1,924 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    start32.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId               db  "INTEL   "    ; OemId                           - 8 bytes

+SectorSize          dw  0             ; Sector Size                     - 2 bytes

+SectorsPerCluster   db  0             ; Sector Per Cluster              - 1 byte

+ReservedSectors     dw  0             ; Reserved Sectors                - 2 bytes

+NoFats              db  0             ; Number of FATs                  - 1 byte

+RootEntries         dw  0             ; Root Entries                    - 2 bytes

+Sectors             dw  0             ; Number of Sectors               - 2 bytes

+Media               db  0             ; Media                           - 1 byte

+SectorsPerFat16     dw  0             ; Sectors Per FAT for FAT12/FAT16 - 2 byte

+SectorsPerTrack     dw  0             ; Sectors Per Track               - 2 bytes

+Heads               dw  0             ; Heads                           - 2 bytes

+HiddenSectors       dd  0             ; Hidden Sectors                  - 4 bytes

+LargeSectors        dd  0             ; Large Sectors                   - 4 bytes

+

+;******************************************************************************

+;

+;The structure for FAT32 starting at offset 36 of the boot sector. (At this point, 

+;the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)

+;

+;******************************************************************************

+

+SectorsPerFat32     dd  0             ; Sectors Per FAT for FAT32       - 4 bytes

+ExtFlags            dw  0             ; Mirror Flag                     - 2 bytes

+FSVersion           dw  0             ; File System Version             - 2 bytes

+RootCluster         dd  0             ; 1st Cluster Number of Root Dir  - 4 bytes

+FSInfo              dw  0             ; Sector Number of FSINFO         - 2 bytes

+BkBootSector        dw  0             ; Sector Number of Bk BootSector  - 2 bytes

+Reserved            db  12 dup(0)     ; Reserved Field                  - 12 bytes

+PhysicalDrive       db  0             ; Physical Drive Number           - 1 byte

+Reserved1           db  0             ; Reserved Field                  - 1 byte

+Signature           db  0             ; Extended Boot Signature         - 1 byte

+VolId               db  "    "        ; Volume Serial Number            - 4 bytes

+FatLabel            db  "           " ; Volume Label                    - 11 bytes

+FileSystemType      db  "FAT32   "    ; File System Type                - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0fff8h                           ; ax = ax & 0xfff8

+        cmp     ax,0fff8h                           ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,2                                ; FatOffset = ClusterNumber * 4

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+        add ebx,01000h                      ; Source of EFI32

+        mov dword ptr [JUMP+2],ebx

+        add ebx,01000h

+        mov esi,ebx                         ; Source of EFILDR32

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+        mov     bx,0008h                    ; Flat data descriptor

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+        db      66h     

+        lgdt    fword ptr [gdtr]

+        db      66h     

+        lidt    fword ptr [idtr]

+

+        mov     eax,cr0

+        or      al,1

+        mov     cr0,eax

+JUMP:

+; jmp far 0010:00020000

+        db  066h

+        db  0eah

+        dd  000020000h

+        dw  00010h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE5_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dd 0                        ; (IDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 8) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start64.S b/uefi/linaro-edk2/DuetPkg/BootSector/start64.S
new file mode 100644
index 0000000..75626b8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start64.S
@@ -0,0 +1,1149 @@
+#------------------------------------------------------------------------------

+#*

+#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>

+#*   This program and the accompanying materials                          

+#*   are licensed and made available under the terms and conditions of the BSD License         

+#*   which accompanies this distribution.  The full text of the license may be found at        

+#*   http://opensource.org/licenses/bsd-license.php                                            

+#*                                                                                             

+#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#*   

+#*    start64.asm

+#*  

+#*   Abstract:

+#*

+#------------------------------------------------------------------------------

+

+

+        .stack: 

+        .486p: 

+        .code16

+

+.equ                        FAT_DIRECTORY_ENTRY_SIZE, 0x020

+.equ                        FAT_DIRECTORY_ENTRY_SHIFT, 5

+.equ                        BLOCK_SIZE, 0x0200

+.equ                        BLOCK_MASK, 0x01ff

+.equ                        BLOCK_SHIFT, 9

+

+        .org 0x0

+

+.global _start

+_start:

+

+Ia32Jump: 

+  jmp   BootSectorEntryPoint  # JMP inst    - 3 bytes

+  nop

+

+OemId:              .ascii  "INTEL   "        # OemId               - 8 bytes

+

+SectorSize:         .word  0                  # Sector Size         - 16 bits

+SectorsPerCluster:  .byte  0                  # Sector Per Cluster  - 8 bits

+ReservedSectors:    .word  0                  # Reserved Sectors    - 16 bits

+NoFats:             .byte  0                  # Number of FATs      - 8 bits

+RootEntries:        .word  0                  # Root Entries        - 16 bits

+Sectors:            .word  0                  # Number of Sectors   - 16 bits

+Media:              .byte  0                  # Media               - 8 bits  - ignored

+SectorsPerFat:      .word  0                  # Sectors Per FAT     - 16 bits

+SectorsPerTrack:    .word  0                  # Sectors Per Track   - 16 bits - ignored

+Heads:              .word  0                  # Heads               - 16 bits - ignored

+HiddenSectors:      .long  0                  # Hidden Sectors      - 32 bits - ignored

+LargeSectors:       .long  0                  # Large Sectors       - 32 bits 

+PhysicalDrive:      .byte  0                  # PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead:        .byte  0                  # Current Head        - 8 bits

+Signature:          .byte  0                  # Signature           - 8 bits  - ignored

+VolId:              .ascii "    "             # Volume Serial Number- 4 bytes

+FatLabel:           .ascii "           "      # Label               - 11 bytes

+SystemId:           .ascii "FAT12   "         # SystemId            - 8 bytes

+

+BootSectorEntryPoint: 

+      # ASSUME  ds:@code"

+      # ASSUME  ss:@code"

+      # ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      # cx = Start Cluster of EfiLdr

+      # dx = Start Cluster of Efivar.bin

+

+# Re use the BPB data stored in Boot Sector

+        movw    $0x7c00,%bp

+

+        pushw   %cx

+# Read Efivar.bin

+#       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        movw    $0x1900,%ax

+        movw    %ax,%es

+        testw   %dx,%dx

+        jnz     CheckVarStoreSize

+

+        movb    $1,%al

+NoVarStore: 

+        pushw   %es

+# Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        movb    %al, %es:(4)

+        jmp     SaveVolumeId

+

+CheckVarStoreSize: 

+        movw    %dx,%di

+        cmpl    $0x4000, %ds:2(%di)

+        movb    $2,%al

+        jne     NoVarStore

+

+LoadVarStore: 

+        movb    $0,%al

+        movb    %al, %es:(4)

+        movw    (%di), %cx

+#       ES:DI = 1500:0

+        xorw    %di,%di

+        pushw   %es

+        movw    $0x1500,%ax

+        movw    %ax,%es

+        call    ReadFile

+SaveVolumeId: 

+        popw    %es

+        movw    VolId(%bp), %ax

+        movw    %ax, %es:(0) 

+        movw    VolId+2(%bp), %ax

+        movw    %ax, %es:(2)

+

+# Read Efildr

+        popw    %cx

+#       cx    = Start Cluster of Efildr -> BS.com has filled already

+#       ES:DI = 2000:0, first cluster will be read again

+        xorw    %di,%di                             # di = 0

+        movw    $0x2000,%ax

+        movw    %ax,%es

+        call    ReadFile

+        movw    %cs,%ax

+        movw    %ax, %cs:JumpSegment

+

+CheckEm64T: 

+        movl $0x80000001,%eax

+#        cpuid

+        .word 0xA20F

+        btl  $29,%edx

+        jc   CheckEm64TPass

+        pushw %cs

+        popw %ds

+        leaw Em64String,%si

+        movw $18,%cx

+        jmp  PrintStringAndHalt

+CheckEm64TPass: 

+JumpFarInstruction: 

+        .byte 0xea

+JumpOffset: 

+        .word 0x200

+JumpSegment: 

+        .word 0x2000

+

+

+

+# ****************************************************************************

+# ReadFile

+#

+# Arguments:

+#   CX    = Start Cluster of File

+#   ES:DI = Buffer to store file content read from disk

+#

+# Return:

+#   (ES << 4 + DI) = end of file content Buffer

+#

+# ****************************************************************************

+ReadFile: 

+# si      = NumberOfClusters

+# cx      = ClusterNumber

+# dx      = CachedFatSectorNumber

+# ds:0000 = CacheFatSectorBuffer

+# es:di   = Buffer to load file

+# bx      = NextClusterNumber

+        pusha

+        movw    $1,%si                              # NumberOfClusters = 1

+        pushw   %cx                                 # Push Start Cluster onto stack

+        movw    $0xfff,%dx                          # CachedFatSectorNumber = 0xfff

+FatChainLoop: 

+        movw    %cx,%ax                             # ax = ClusterNumber    

+        andw    $0xff8,%ax                          # ax = ax & 0xff8

+        cmpw    $0xff8,%ax                          # See if this is the last cluster

+        je      FoundLastCluster                    # Jump if last cluster found

+        movw    %cx,%ax                             # ax = ClusterNumber

+        shlw    %ax                                 # ax = ClusterNumber * 2

+        addw    %cx,%ax                             # ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3

+        shrw    %ax                                 # FatOffset = ClusterNumber*3 / 2

+        pushw   %si                                 # Save si

+        movw    %ax,%si                             # si = FatOffset

+        shrw    $BLOCK_SHIFT, %ax                   # ax = FatOffset >> BLOCK_SHIFT

+        addw    ReservedSectors(%bp), %ax           # ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        andw    $BLOCK_MASK, %si                    # si = FatOffset & BLOCK_MASK

+        cmpw    %dx,%ax                             # Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        movw    $2,%bx

+        pushw   %es

+        pushw   %ds

+        popw    %es

+        call    ReadBlocks                          # Read 2 blocks starting at AX storing at ES:DI

+        popw    %es

+        movw    %ax,%dx                             # CachedFatSectorNumber = FatSectorNumber

+SkipFatRead: 

+        movw    (%si), %bx                          # bx = NextClusterNumber

+        movw    %cx,%ax                             # ax = ClusterNumber

+        andw    $1,%ax                              # See if this is an odd cluster number

+        je      EvenFatEntry

+        shrw    $4,%bx                              # NextClusterNumber = NextClusterNumber >> 4

+EvenFatEntry: 

+        andw    $0xfff,%bx                          # Strip upper 4 bits of NextClusterNumber

+        popw    %si                                 # Restore si

+        decw    %bx                                 # bx = NextClusterNumber - 1

+        cmpw    %cx,%bx                             # See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        incw    %bx                                 # bx = NextClusterNumber

+        incw    %si                                 # NumberOfClusters++

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters: 

+        incw    %bx

+        popw    %ax                                 # ax = StartCluster

+        pushw   %bx                                 # StartCluster = NextClusterNumber

+        movw    %bx,%cx                             # ClusterNumber = NextClusterNumber

+        subw    $2,%ax                              # ax = StartCluster - 2

+        xorb    %bh,%bh

+        movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster

+        mulw    %bx                                 # ax = (StartCluster - 2) * SectorsPerCluster

+        addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        pushw   %ax                                 # save start sector

+        movw    %si,%ax                             # ax = NumberOfClusters

+        mulw    %bx                                 # ax = NumberOfClusters * SectorsPerCluster

+        movw    %ax,%bx                             # bx = Number of Sectors

+        popw    %ax                                 # ax = Start Sector

+        call    ReadBlocks

+        movw    $1,%si                              # NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster: 

+        popw    %cx

+        popa

+        ret

+

+

+# ****************************************************************************

+# ReadBlocks - Reads a set of blocks from a block device

+#

+# AX    = Start LBA

+# BX    = Number of Blocks to Read

+# ES:DI = Buffer to store sectors read from disk

+# ****************************************************************************

+

+# cx = Blocks

+# bx = NumberOfBlocks

+# si = StartLBA

+

+ReadBlocks: 

+        pusha

+        addl    LBAOffsetForBootSector(%bp), %eax   # Add LBAOffsetForBootSector to Start LBA

+        addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA

+        movl    %eax,%esi                           # esi = Start LBA

+        movw    %bx,%cx                             # cx = Number of blocks to read

+ReadCylinderLoop: 

+        movw    $0x7bfc,%bp                         # bp = 0x7bfc

+        movl    %esi,%eax                           # eax = Start LBA

+        xorl    %edx,%edx                           # edx = 0

+        movzwl  (%bp), %ebx                         # bx = MaxSector

+        divl    %ebx                                # ax = StartLBA / MaxSector

+        incw    %dx                                 # dx = (StartLBA % MaxSector) + 1

+

+        movw    (%bp), %bx                          # bx = MaxSector

+        subw    %dx,%bx                             # bx = MaxSector - Sector

+        incw    %bx                                 # bx = MaxSector - Sector + 1

+        cmpw    %bx,%cx                             # Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        movw    %cx,%bx                             # bx = Blocks

+LimitTransfer: 

+        pushw   %ax                                 # save ax

+        movw    %es,%ax                             # ax = es

+        shrw    $(BLOCK_SHIFT-4), %ax               # ax = Number of blocks into mem system

+        andw    $0x7f,%ax                           # ax = Number of blocks into current seg

+        addw    %bx,%ax                             # ax = End Block number of transfer

+        cmpw    $0x80,%ax                           # See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               # Branch if not crossing 64K boundry

+        subw    $0x80,%ax                           # ax = Number of blocks past 64K boundry

+        subw    %ax,%bx                             # Decrease transfer size by block overage

+NotCrossing64KBoundry: 

+        popw    %ax                                 # restore ax

+

+        pushw   %cx

+        movb    %dl,%cl                             # cl = (StartLBA % MaxSector) + 1 = Sector

+        xorw    %dx,%dx                             # dx = 0

+        divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder  

+                                                    # dx = ax % (MaxHead + 1) = Head

+

+        pushw   %bx                                 # Save number of blocks to transfer

+        movb    %dl,%dh                             # dh = Head

+        movw    $0x7c00,%bp                         # bp = 0x7c00

+        movb    PhysicalDrive(%bp), %dl             # dl = Drive Number

+        movb    %al,%ch                             # ch = Cylinder

+        movb    %bl,%al                             # al = Blocks

+        movb    $2,%ah                              # ah = Function 2

+        movw    %di,%bx                             # es:bx = Buffer address

+        int     $0x13

+        jc      DiskError

+        popw    %bx

+        popw    %cx

+        movzwl  %bx,%ebx

+        addl    %ebx,%esi                           # StartLBA = StartLBA + NumberOfBlocks

+        subw    %bx,%cx                             # Blocks = Blocks - NumberOfBlocks

+        movw    %es,%ax

+        shlw    $(BLOCK_SHIFT-4), %bx

+        addw    %bx,%ax

+        movw    %ax,%es                             # es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmpw    $0,%cx

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError: 

+        pushw %cs

+        popw %ds

+        leaw ErrorString,%si

+        movw $7,%cx

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt: 

+        movw $0xb800,%ax

+        movw %ax,%es

+        movw $160,%di

+        rep 

+        movsw       

+Halt: 

+        jmp   Halt

+

+ErrorString: 

+        .byte 'S', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c, '!',0x0c

+

+        .org     0x01fa

+LBAOffsetForBootSector: 

+        .long 0x0

+

+        .org    0x01fe

+        .word 0xaa55

+

+#******************************************************************************

+#******************************************************************************

+#******************************************************************************

+

+.equ                 DELAY_PORT, 0x0ed           # Port to use for 1uS delay

+.equ                 KBD_CONTROL_PORT, 0x060     # 8042 control port     

+.equ                 KBD_STATUS_PORT, 0x064      # 8042 status port      

+.equ                 WRITE_DATA_PORT_CMD, 0x0d1  # 8042 command to write the data port

+.equ                 ENABLE_A20_CMD, 0x0df       # 8042 command to enable A20

+

+        .org     0x200

+        jmp start

+Em64String: 

+.byte 'E', 0x0c, 'm', 0x0c, '6', 0x0c, '4', 0x0c, 'T', 0x0c, ' ', 0x0c, 'U', 0x0c, 'n', 0x0c, 's', 0x0c, 'u', 0x0c, 'p', 0x0c, 'p', 0x0c, 'o', 0x0c, 'r', 0x0c, 't', 0x0c, 'e', 0x0c, 'd', 0x0c, '!', 0x0c

+

+start:  

+        movw %cs,%ax

+        movw %ax,%ds

+        movw %ax,%es

+        movw %ax,%ss

+        movw $MyStack, %sp

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[160],'a'

+#        mov ax,cs

+#        mov es,ax

+

+        movl $0,%ebx

+        leal MemoryMap, %edi

+MemMapLoop: 

+        movl $0xe820,%eax

+        movl $20,%ecx

+        movl $0x534d4150, %edx  # SMAP

+        int $0x15

+        jc  MemMapDone

+        addl $20,%edi

+        cmpl $0,%ebx

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone: 

+        leal MemoryMap, %eax

+        subl %eax,%edi                      # Get the address of the memory map

+        movl %edi, MemoryMapSize            # Save the size of the memory map

+

+        xorl    %ebx,%ebx

+        movw    %cs,%bx                     # BX=segment

+        shll    $4,%ebx                     # BX="linear" address of segment base

+        leal    GDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of gdt

+        movl    %eax, (gdtr + 2)            # Put address of gdt into the gdtr

+        leal    IDT_BASE(%ebx), %eax        # EAX=PHYSICAL address of idt

+        movl    %eax, (idtr + 2)            # Put address of idt into the idtr

+        leal    MemoryMapSize(%ebx), %edx   # Physical base address of the memory map

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[162],'b'

+#        mov ax,cs

+#        mov es,ax

+

+#

+# Enable A20 Gate 

+#

+

+        movw $0x2401,%ax                    # Enable A20 Gate

+        int $0x15

+        jnc A20GateEnabled                  # Jump if it suceeded

+

+#

+# If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+#

+

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        movb    $WRITE_DATA_PORT_CMD, %al   # 8042 cmd to write output port

+        outb    %al, $KBD_STATUS_PORT       # Send command to the 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 # Jump if the 8042 timed out

+        movb    $ENABLE_A20_CMD, %al        # gate address bit 20 on

+        outb    %al, $KBD_CONTROL_PORT      # Send command to thre 8042

+        call    Empty8042InputBuffer        # Empty the Input Buffer on the 8042 controller

+        movw    $25,%cx                     # Delay 25 uS for the command to complete on the 8042

+Delay25uS: 

+        outw    %ax, $DELAY_PORT            # Delay 1 uS

+        loop    Delay25uS

+Timeout8042: 

+

+

+A20GateEnabled: 

+

+#

+# DISABLE INTERRUPTS - Entering Protected Mode

+#

+

+        cli

+

+#        mov ax,0b800h

+#        mov es,ax

+#        mov byte ptr es:[164],'c'

+#        mov ax,cs

+#        mov es,ax

+

+    leal OffsetIn32BitProtectedMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetIn32BitProtectedMode 

+

+    leal OffsetInLongMode, %eax

+    addl $0x20000+0x6,%eax

+    movl %eax, OffsetInLongMode 

+

+    #

+    # load GDT

+    #

+    .byte 0x66

+    lgdt    gdtr

+

+    #

+    # Enable Protect Mode (set CR0.PE=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    orl   $0x1,%eax       # Set PE=1

+    movl  %eax, %cr0      # Write CR0.

+    .byte 0x66

+    .byte 0xea                        # jmp far 16:32

+OffsetIn32BitProtectedMode: 

+    .long 0x0000000                   # offset $+8   (In32BitProtectedMode)

+    .word 0x10                        # selector  (flat CS)

+In32BitProtectedMode: 

+

+#

+# Entering Long Mode

+#

+    .byte 0x66

+    movw $8,%ax

+    movw %ax,%ds

+    movw %ax,%es

+    movw %ax,%ss

+

+    #

+    # Enable the 64-bit page-translation-table entries by

+    # setting CR4.PAE=1 (this is _required_ before activating

+    # long mode). Paging is not enabled until after long mode

+    # is enabled.

+    #

+    .byte 0xf

+    .byte 0x20

+    .byte 0xe0

+#    mov eax, cr4

+    btsl $5,%eax

+    .byte 0xf

+    .byte 0x22

+    .byte 0xe0

+#    mov cr4, eax

+

+    #

+    # This is the Trapolean Page Tables that are guarenteed

+    #  under 4GB.

+    #

+    # Address Map:

+    #    10000 ~    12000 - efildr (loaded)

+    #    20000 ~    21000 - start64.com

+    #    21000 ~    22000 - efi64.com

+    #    22000 ~    90000 - efildr

+    #    90000 ~    96000 - 4G pagetable (will be reload later)

+    #

+    .byte 0xb8

+    .long 0x90000

+#    mov eax, 90000h

+    movl %eax, %cr3

+

+    #

+    # Enable long mode (set EFER.LME=1).

+    #

+    .byte 0xb9

+    .long 0xc0000080

+#    mov   ecx, 0c0000080h ; EFER MSR number.

+    .byte 0xf

+    .byte 0x32

+#    rdmsr                 ; Read EFER.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x8

+#    bts   eax, 8          ; Set LME=1.

+    .byte 0xf

+    .byte 0x30

+#    wrmsr                 ; Write EFER.

+

+    #

+    # Enable paging to activate long mode (set CR0.PG=1)

+    #

+    movl  %cr0, %eax      # Read CR0.

+    .byte 0xf

+    .byte 0xba

+    .byte 0xe8

+    .byte 0x1f

+#    bts   eax, 31         ; Set PG=1.

+    movl  %eax, %cr0      # Write CR0.

+    jmp   GoToLongMode

+GoToLongMode: 

+

+    .byte 0x67

+    .byte 0xea                  # Far Jump $+9:Selector to reload CS

+OffsetInLongMode: 

+    .long 00000000              #   $+9 Offset is ensuing instruction boundary

+    .word 0x38                  #   Selector is our code selector, 38h

+

+InLongMode: 

+    .byte 0x66

+    movw    $0x30,%ax

+    movw    %ax,%ds

+

+    .byte 0x66

+    movw    $0x18,%ax

+    movw    %ax,%es

+    movw    %ax,%ss

+    movw    %ax,%ds

+

+    .byte 0xbd

+    .long 0x400000

+#    mov ebp,000400000h                  ; Destination of EFILDR32

+    .byte 0xbb

+    .long 0x70000

+#    mov ebx,000070000h                  ; Length of copy

+

+    #

+    # load idt later

+    #

+    .byte 0x48

+    .byte 0x33

+    .byte 0xc0

+#    xor rax, rax

+    .byte 0x66

+     movw $idtr, %ax

+    .byte 0x48

+    .byte 0x5

+    .long 0x20000

+#    add rax, 20000h

+

+    .byte 0xf

+    .byte 0x1

+    .byte 0x18

+#    lidt    fword ptr [rax]

+

+    .byte 0x48

+    .byte 0xc7

+    .byte 0xc0

+    .long 0x21000

+#   mov rax, 21000h

+    .byte 0x50

+#   push rax

+

+# ret

+    .byte 0xc3

+

+Empty8042InputBuffer: 

+        movw $0,%cx

+Empty8042Loop: 

+        outw    %ax, $DELAY_PORT            # Delay 1us

+        inb     $KBD_STATUS_PORT, %al       # Read the 8042 Status Port

+        andb    $0x2,%al                    # Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               # Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+##############################################################################

+# data

+##############################################################################

+

+        .p2align 1

+

+        gdtr:    .long  GDT_END - GDT_BASE - 1  # GDT limit 

+        .long 0                     # (GDT base gets set above)

+##############################################################################

+#   global descriptor table (GDT)

+##############################################################################

+

+        .p2align 1

+

+GDT_BASE: 

+# null descriptor

+.equ                NULL_SEL, .-GDT_BASE    # Selector [0x0]

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+.equ            LINEAR_SEL, .-GDT_BASE  # Selector [0x8]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+.equ            LINEAR_CODE_SEL, .-GDT_BASE # Selector [0x10]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+.equ            SYS_DATA_SEL, .-GDT_BASE # Selector [0x18]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+.equ            SYS_CODE_SEL, .-GDT_BASE # Selector [0x20]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE3_SEL, .-GDT_BASE  # Selector [0x28]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+#

+# system data segment descriptor

+#

+.equ              SYS_DATA64_SEL, .-GDT_BASE # Selector [0x30]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xCF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+#

+# system code segment descriptor

+#

+.equ              SYS_CODE64_SEL, .-GDT_BASE # Selector [0x38]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # P | DPL [1..2] | 1   | 1   | C | R | A

+        .byte 0xAF      # G | D   | L    | AVL | Segment [19..16]

+        .byte 0

+

+# spare segment descriptor

+.equ        SPARE4_SEL, .-GDT_BASE    # Selector [0x40]

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

+        .p2align 1

+

+

+

+idtr:   .long  IDT_END - IDT_BASE - 1 # IDT limit

+        .quad 0                       # (IDT base gets set above)

+

+##############################################################################

+#   interrupt descriptor table (IDT)

+#

+#   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+#       mappings.  This implementation only uses the system timer and all other

+#       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+#       for convenience.

+##############################################################################

+

+#idt_tag db "IDT",0     

+        .p2align 1

+

+

+IDT_BASE: 

+# divide by zero (INT 0)

+.equ                DIV_ZERO_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# debug exception (INT 1)

+.equ                DEBUG_EXCEPT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# NMI (INT 2)

+.equ                NMI_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# soft breakpoint (INT 3)

+.equ                BREAKPOINT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# overflow (INT 4)

+.equ                OVERFLOW_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# bounds check (INT 5)

+.equ                BOUNDS_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid opcode (INT 6)

+.equ                INVALID_OPCODE_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# device not available (INT 7)

+.equ                DEV_NOT_AVAIL_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# double fault (INT 8)

+.equ                DOUBLE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Coprocessor segment overrun - reserved (INT 9)

+.equ                RSVD_INTR_SEL1, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# invalid TSS (INT 0ah)

+.equ                INVALID_TSS_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# segment not present (INT 0bh)

+.equ                SEG_NOT_PRESENT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# stack fault (INT 0ch)

+.equ                STACK_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# general protection (INT 0dh)

+.equ                GP_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# page fault (INT 0eh)

+.equ                PAGE_FAULT_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Intel reserved - do not use (INT 0fh)

+.equ                RSVD_INTR_SEL2, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# floating point error (INT 10h)

+.equ                FLT_POINT_ERR_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# alignment check (INT 11h)

+.equ                ALIGNMENT_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# machine check (INT 12h)

+.equ                MACHINE_CHECK_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# SIMD floating-point exception (INT 13h)

+.equ                SIMD_EXCEPTION_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        .fill 85 * 16, 1, 0   # db (85 * 16) dup(0)

+

+# IRQ 0 (System timer) - (INT 68h)

+.equ                IRQ0_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 1 (8042 Keyboard controller) - (INT 69h)

+.equ                IRQ1_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+.equ                IRQ2_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 3 (COM 2) - (INT 6bh)

+.equ                IRQ3_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 4 (COM 1) - (INT 6ch)

+.equ                IRQ4_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 5 (LPT 2) - (INT 6dh)

+.equ                IRQ5_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 6 (Floppy controller) - (INT 6eh)

+.equ                IRQ6_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 7 (LPT 1) - (INT 6fh)

+.equ                IRQ7_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 8 (RTC Alarm) - (INT 70h)

+.equ                IRQ8_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 9 - (INT 71h)

+.equ                IRQ9_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 10 - (INT 72h)

+.equ                 IRQ10_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 11 - (INT 73h)

+.equ                 IRQ11_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 12 (PS/2 mouse) - (INT 74h)

+.equ                 IRQ12_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 13 (Floating point error) - (INT 75h)

+.equ                 IRQ13_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 14 (Secondary IDE) - (INT 76h)

+.equ                 IRQ14_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+# IRQ 15 (Primary IDE) - (INT 77h)

+.equ                 IRQ15_SEL, .-IDT_BASE

+        .word 0               # offset 15:0

+        .long SYS_CODE64_SEL  # selector 15:0

+        .byte 0               # 0 for interrupt gate

+        .byte 0x0e | 0x80     # type = 386 interrupt gate, present

+        .word 0               # offset 31:16

+        .long 0               # offset 63:32

+        .long 0               # 0 for reserved

+

+IDT_END: 

+

+        .p2align 1

+

+MemoryMapSize:  .long 0

+MemoryMap:  .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+        .long 0,0,0,0,0,0,0,0

+

+        .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        .org 0x0fe0

+MyStack:    

+        # below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        #    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        #    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        #    8259.c

+

+        int $8

+        iret

+

+        int $9

+        iret

+

+        int $10

+        iret

+

+        int $11

+        iret

+

+        int $12

+        iret

+

+        int $13

+        iret

+

+        int $14

+        iret

+

+        int $15

+        iret

+

+

+        .org 0x0ffe

+BlockSignature: 

+        .word 0xaa55

+

diff --git a/uefi/linaro-edk2/DuetPkg/BootSector/start64.asm b/uefi/linaro-edk2/DuetPkg/BootSector/start64.asm
new file mode 100644
index 0000000..e368bf3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/BootSector/start64.asm
@@ -0,0 +1,1147 @@
+;------------------------------------------------------------------------------

+;*

+;*   Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>

+;*   This program and the accompanying materials                          

+;*   are licensed and made available under the terms and conditions of the BSD License         

+;*   which accompanies this distribution.  The full text of the license may be found at        

+;*   http://opensource.org/licenses/bsd-license.php                                            

+;*                                                                                             

+;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+;*   

+;*    start64.asm

+;*  

+;*   Abstract:

+;*

+;------------------------------------------------------------------------------

+

+        .model  small

+        .stack

+        .486p

+        .code

+

+FAT_DIRECTORY_ENTRY_SIZE    EQU     020h

+FAT_DIRECTORY_ENTRY_SHIFT   EQU     5

+BLOCK_SIZE                  EQU     0200h

+BLOCK_MASK                  EQU     01ffh

+BLOCK_SHIFT                 EQU     9

+

+        org 0h

+Ia32Jump:

+  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes

+  nop

+

+OemId             db  "INTEL   "    ; OemId               - 8 bytes

+

+SectorSize        dw  0             ; Sector Size         - 16 bits

+SectorsPerCluster db  0             ; Sector Per Cluster  - 8 bits

+ReservedSectors   dw  0             ; Reserved Sectors    - 16 bits

+NoFats            db  0             ; Number of FATs      - 8 bits

+RootEntries       dw  0             ; Root Entries        - 16 bits

+Sectors           dw  0             ; Number of Sectors   - 16 bits

+Media             db  0             ; Media               - 8 bits  - ignored

+SectorsPerFat     dw  0             ; Sectors Per FAT     - 16 bits

+SectorsPerTrack   dw  0             ; Sectors Per Track   - 16 bits - ignored

+Heads             dw  0             ; Heads               - 16 bits - ignored

+HiddenSectors     dd  0             ; Hidden Sectors      - 32 bits - ignored

+LargeSectors      dd  0             ; Large Sectors       - 32 bits 

+PhysicalDrive     db  0             ; PhysicalDriveNumber - 8 bits  - ignored

+CurrentHead       db  0             ; Current Head        - 8 bits

+Signature         db  0             ; Signature           - 8 bits  - ignored

+VolId             db  "    "        ; Volume Serial Number- 4 bytes

+FatLabel          db  "           " ; Label               - 11 bytes

+SystemId          db  "FAT12   "    ; SystemId            - 8 bytes

+

+BootSectorEntryPoint:

+        ASSUME  ds:@code

+        ASSUME  ss:@code

+      ; ds = 1000, es = 2000 + x (size of first cluster >> 4)

+      ; cx = Start Cluster of EfiLdr

+      ; dx = Start Cluster of Efivar.bin

+

+; Re use the BPB data stored in Boot Sector

+        mov     bp,07c00h

+

+        push    cx

+; Read Efivar.bin

+;       1000:dx    = DirectoryEntry of Efivar.bin -> BS.com has filled already

+        mov     ax,01900h

+        mov     es,ax

+        test    dx,dx

+        jnz     CheckVarStoreSize

+

+        mov     al,1

+NoVarStore:

+        push    es

+; Set the 5th byte start @ 0:19000 to non-zero indicating we should init var store header in DxeIpl

+        mov     byte ptr es:[4],al

+        jmp     SaveVolumeId

+

+CheckVarStoreSize:

+        mov     di,dx

+        cmp     dword ptr ds:[di+2], 04000h

+        mov     al,2

+        jne     NoVarStore

+

+LoadVarStore:

+        mov     al,0

+        mov     byte ptr es:[4],al

+        mov     cx,word ptr[di]

+;       ES:DI = 1500:0

+        xor     di,di

+        push    es

+        mov     ax,01500h

+        mov     es,ax

+        call    ReadFile

+SaveVolumeId:

+        pop     es

+        mov     ax,word ptr [bp+VolId]

+        mov     word ptr es:[0],ax                  ; Save Volume Id to 0:19000. we will find the correct volume according to this VolumeId

+        mov     ax,word ptr [bp+VolId+2]

+        mov     word ptr es:[2],ax

+

+; Read Efildr

+        pop     cx

+;       cx    = Start Cluster of Efildr -> BS.com has filled already

+;       ES:DI = 2000:0, first cluster will be read again

+        xor     di,di                               ; di = 0

+        mov     ax,02000h

+        mov     es,ax

+        call    ReadFile

+        mov     ax,cs

+        mov     word ptr cs:[JumpSegment],ax

+

+CheckEm64T:

+        mov  eax, 080000001h

+;        cpuid

+        dw   0A20Fh

+        bt   edx, 29

+        jc   CheckEm64TPass

+        push cs

+        pop  ds

+        lea  si, [Em64String]

+        mov  cx, 18

+        jmp  PrintStringAndHalt

+CheckEm64TPass:

+JumpFarInstruction:

+        db      0eah

+JumpOffset:

+        dw      0200h

+JumpSegment:

+        dw      2000h

+

+

+

+; ****************************************************************************

+; ReadFile

+;

+; Arguments:

+;   CX    = Start Cluster of File

+;   ES:DI = Buffer to store file content read from disk

+;

+; Return:

+;   (ES << 4 + DI) = end of file content Buffer

+;

+; ****************************************************************************

+ReadFile:

+; si      = NumberOfClusters

+; cx      = ClusterNumber

+; dx      = CachedFatSectorNumber

+; ds:0000 = CacheFatSectorBuffer

+; es:di   = Buffer to load file

+; bx      = NextClusterNumber

+        pusha

+        mov     si,1                                ; NumberOfClusters = 1

+        push    cx                                  ; Push Start Cluster onto stack

+        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff

+FatChainLoop:

+        mov     ax,cx                               ; ax = ClusterNumber    

+        and     ax,0ff8h                            ; ax = ax & 0xff8

+        cmp     ax,0ff8h                            ; See if this is the last cluster

+        je      FoundLastCluster                    ; Jump if last cluster found

+        mov     ax,cx                               ; ax = ClusterNumber

+        shl     ax,1                                ; ax = ClusterNumber * 2

+        add     ax,cx                               ; ax = ClusterNumber * 2 + ClusterNumber = ClusterNumber * 3

+        shr     ax,1                                ; FatOffset = ClusterNumber*3 / 2

+        push    si                                  ; Save si

+        mov     si,ax                               ; si = FatOffset

+        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT

+        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)

+        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK

+        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber

+        je      SkipFatRead

+        mov     bx,2                                

+        push    es

+        push    ds

+        pop     es

+        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI

+        pop     es

+        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber

+SkipFatRead:

+        mov     bx,word ptr [si]                    ; bx = NextClusterNumber

+        mov     ax,cx                               ; ax = ClusterNumber

+        and     ax,1                                ; See if this is an odd cluster number

+        je      EvenFatEntry

+        shr     bx,4                                ; NextClusterNumber = NextClusterNumber >> 4

+EvenFatEntry:

+        and     bx,0fffh                            ; Strip upper 4 bits of NextClusterNumber

+        pop     si                                  ; Restore si

+        dec     bx                                  ; bx = NextClusterNumber - 1

+        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber

+        jne     ReadClusters

+        inc     bx                                  ; bx = NextClusterNumber

+        inc     si                                  ; NumberOfClusters++

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        jmp     FatChainLoop

+ReadClusters:

+        inc     bx

+        pop     ax                                  ; ax = StartCluster

+        push    bx                                  ; StartCluster = NextClusterNumber

+        mov     cx,bx                               ; ClusterNumber = NextClusterNumber

+        sub     ax,2                                ; ax = StartCluster - 2

+        xor     bh,bh                               

+        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster

+        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster

+        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster

+        push    ax                                  ; save start sector

+        mov     ax,si                               ; ax = NumberOfClusters

+        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster

+        mov     bx,ax                               ; bx = Number of Sectors

+        pop     ax                                  ; ax = Start Sector

+        call    ReadBlocks

+        mov     si,1                                ; NumberOfClusters = 1

+        jmp     FatChainLoop

+FoundLastCluster:

+        pop     cx

+        popa

+        ret

+

+

+; ****************************************************************************

+; ReadBlocks - Reads a set of blocks from a block device

+;

+; AX    = Start LBA

+; BX    = Number of Blocks to Read

+; ES:DI = Buffer to store sectors read from disk

+; ****************************************************************************

+

+; cx = Blocks

+; bx = NumberOfBlocks

+; si = StartLBA

+

+ReadBlocks:

+        pusha

+        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA

+        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA

+        mov     esi,eax                             ; esi = Start LBA

+        mov     cx,bx                               ; cx = Number of blocks to read

+ReadCylinderLoop:

+        mov     bp,07bfch                           ; bp = 0x7bfc

+        mov     eax,esi                             ; eax = Start LBA

+        xor     edx,edx                             ; edx = 0

+        movzx   ebx,word ptr [bp]                   ; bx = MaxSector

+        div     ebx                                 ; ax = StartLBA / MaxSector

+        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

+

+        mov     bx,word ptr [bp]                    ; bx = MaxSector

+        sub     bx,dx                               ; bx = MaxSector - Sector

+        inc     bx                                  ; bx = MaxSector - Sector + 1

+        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)

+        jg      LimitTransfer

+        mov     bx,cx                               ; bx = Blocks

+LimitTransfer:

+        push    ax                                  ; save ax

+        mov     ax,es                               ; ax = es

+        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system

+        and     ax,07fh                             ; ax = Number of blocks into current seg

+        add     ax,bx                               ; ax = End Block number of transfer

+        cmp     ax,080h                             ; See if it crosses a 64K boundry

+        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry

+        sub     ax,080h                             ; ax = Number of blocks past 64K boundry

+        sub     bx,ax                               ; Decrease transfer size by block overage

+NotCrossing64KBoundry:

+        pop     ax                                  ; restore ax

+

+        push    cx

+        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector

+        xor     dx,dx                               ; dx = 0

+        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  

+                                                    ; dx = ax % (MaxHead + 1) = Head

+

+        push    bx                                  ; Save number of blocks to transfer

+        mov     dh,dl                               ; dh = Head

+        mov     bp,07c00h                           ; bp = 0x7c00

+        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number

+        mov     ch,al                               ; ch = Cylinder

+        mov     al,bl                               ; al = Blocks

+        mov     ah,2                                ; ah = Function 2

+        mov     bx,di                               ; es:bx = Buffer address

+        int     013h

+        jc      DiskError

+        pop     bx

+        pop     cx

+        movzx   ebx,bx

+        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks

+        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks

+        mov     ax,es

+        shl     bx,(BLOCK_SHIFT-4)

+        add     ax,bx

+        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE

+        cmp     cx,0

+        jne     ReadCylinderLoop

+        popa

+        ret

+

+DiskError:

+        push cs

+        pop  ds

+        lea  si, [ErrorString]

+        mov  cx, 7

+        jmp  PrintStringAndHalt

+

+PrintStringAndHalt:

+        mov  ax,0b800h

+        mov  es,ax

+        mov  di,160

+        rep  movsw

+Halt:

+        jmp   Halt

+

+ErrorString:

+        db 'S', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '!', 0ch

+

+        org     01fah

+LBAOffsetForBootSector:

+        dd      0h

+

+        org     01feh

+        dw      0aa55h

+

+;******************************************************************************

+;******************************************************************************

+;******************************************************************************

+

+DELAY_PORT           equ     0edh    ; Port to use for 1uS delay

+KBD_CONTROL_PORT     equ     060h    ; 8042 control port     

+KBD_STATUS_PORT      equ     064h    ; 8042 status port      

+WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port

+ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

+

+        org     200h

+        jmp start

+Em64String:

+        db 'E', 0ch, 'm', 0ch, '6', 0ch, '4', 0ch, 'T', 0ch, ' ', 0ch, 'U', 0ch, 'n', 0ch, 's', 0ch, 'u', 0ch, 'p', 0ch, 'p', 0ch, 'o', 0ch, 'r', 0ch, 't', 0ch, 'e', 0ch, 'd', 0ch, '!', 0ch

+

+start:  

+        mov ax,cs

+        mov ds,ax

+        mov es,ax

+        mov ss,ax

+        mov sp,MyStack

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[160],'a'

+;        mov ax,cs

+;        mov es,ax

+

+        mov ebx,0

+        lea edi,MemoryMap

+MemMapLoop:

+        mov eax,0e820h

+        mov ecx,20

+        mov edx,'SMAP'

+        int 15h

+        jc  MemMapDone

+        add edi,20

+        cmp ebx,0

+        je  MemMapDone

+        jmp MemMapLoop

+MemMapDone:

+        lea eax,MemoryMap

+        sub edi,eax                         ; Get the address of the memory map

+        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

+

+        xor     ebx,ebx

+        mov     bx,cs                       ; BX=segment

+        shl     ebx,4                       ; BX="linear" address of segment base

+        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt

+        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr

+        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt

+        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr

+        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[162],'b'

+;        mov ax,cs

+;        mov es,ax

+

+;

+; Enable A20 Gate 

+;

+

+        mov ax,2401h                        ; Enable A20 Gate

+        int 15h

+        jnc A20GateEnabled                  ; Jump if it suceeded

+

+;

+; If INT 15 Function 2401 is not supported, then attempt to Enable A20 manually.

+;

+

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        mov     al,WRITE_DATA_PORT_CMD      ; 8042 cmd to write output port

+        out     KBD_STATUS_PORT,al          ; Send command to the 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        jnz     Timeout8042                 ; Jump if the 8042 timed out

+        mov     al,ENABLE_A20_CMD           ; gate address bit 20 on

+        out     KBD_CONTROL_PORT,al         ; Send command to thre 8042

+        call    Empty8042InputBuffer        ; Empty the Input Buffer on the 8042 controller

+        mov     cx,25                       ; Delay 25 uS for the command to complete on the 8042

+Delay25uS:

+        out     DELAY_PORT,ax               ; Delay 1 uS

+        loop    Delay25uS                       

+Timeout8042:

+

+

+A20GateEnabled:

+

+;

+; DISABLE INTERRUPTS - Entering Protected Mode

+;

+

+        cli                             

+

+;        mov ax,0b800h

+;        mov es,ax

+;        mov byte ptr es:[164],'c'

+;        mov ax,cs

+;        mov es,ax

+

+    lea eax, OffsetIn32BitProtectedMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetIn32BitProtectedMode], eax

+

+    lea eax, OffsetInLongMode

+    add eax, 20000h + 6h

+    mov dword ptr[OffsetInLongMode], eax

+

+    ;

+    ; load GDT

+    ;

+    db      66h     

+    lgdt    fword ptr [gdtr]

+

+    ;

+    ; Enable Protect Mode (set CR0.PE=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    or    eax, 1h         ; Set PE=1

+    mov   cr0, eax        ; Write CR0.

+    db    066h

+    db    0eah                        ; jmp far 16:32

+OffsetIn32BitProtectedMode:

+    dd    00000000h                   ; offset $+8   (In32BitProtectedMode)

+    dw    10h                         ; selector  (flat CS)

+In32BitProtectedMode:

+

+;

+; Entering Long Mode

+;

+    db   66h

+    mov  ax, 8

+    mov  ds, ax

+    mov  es, ax

+    mov  ss, ax

+

+    ;

+    ; Enable the 64-bit page-translation-table entries by

+    ; setting CR4.PAE=1 (this is _required_ before activating

+    ; long mode). Paging is not enabled until after long mode

+    ; is enabled.

+    ;

+    db 0fh

+    db 20h

+    db 0e0h

+;    mov eax, cr4

+    bts eax, 5

+    db 0fh

+    db 22h

+    db 0e0h

+;    mov cr4, eax

+

+    ;

+    ; This is the Trapolean Page Tables that are guarenteed

+    ;  under 4GB.

+    ;

+    ; Address Map:

+    ;    10000 ~    12000 - efildr (loaded)

+    ;    20000 ~    21000 - start64.com

+    ;    21000 ~    22000 - efi64.com

+    ;    22000 ~    90000 - efildr

+    ;    90000 ~    96000 - 4G pagetable (will be reload later)

+    ;

+    db  0b8h

+    dd  90000h

+;    mov eax, 90000h

+    mov cr3, eax

+

+    ;

+    ; Enable long mode (set EFER.LME=1).

+    ;

+    db  0b9h

+    dd  0c0000080h

+;    mov   ecx, 0c0000080h ; EFER MSR number.

+    db 0fh

+    db 32h

+;    rdmsr                 ; Read EFER.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    08h

+;    bts   eax, 8          ; Set LME=1.

+    db 0fh

+    db 30h

+;    wrmsr                 ; Write EFER.

+

+    ;

+    ; Enable paging to activate long mode (set CR0.PG=1)

+    ;

+    mov   eax, cr0        ; Read CR0.

+    db    0fh

+    db    0bah

+    db    0e8h

+    db    01fh

+;    bts   eax, 31         ; Set PG=1.

+    mov   cr0, eax        ; Write CR0.

+    jmp   GoToLongMode

+GoToLongMode:

+

+    db      067h

+    db      0eah                ; Far Jump $+9:Selector to reload CS

+OffsetInLongMode:

+    dd      00000000            ;   $+9 Offset is ensuing instruction boundary

+    dw      038h                ;   Selector is our code selector, 38h

+

+InLongMode:

+    db   66h

+    mov     ax, 30h

+    mov     ds, ax

+

+    db   66h

+    mov     ax, 18h

+    mov     es, ax

+    mov     ss, ax

+    mov     ds, ax

+

+    db 0bdh

+    dd 400000h

+;    mov ebp,000400000h                  ; Destination of EFILDR32

+    db 0bbh

+    dd 70000h

+;    mov ebx,000070000h                  ; Length of copy

+

+    ;

+    ; load idt later

+    ;

+    db 48h

+    db 33h

+    db 0c0h

+;    xor rax, rax

+    db 66h

+    mov ax, offset idtr

+    db 48h

+    db 05h

+    dd 20000h

+;    add rax, 20000h

+

+    db 0fh

+    db 01h

+    db 18h

+;    lidt    fword ptr [rax]

+

+    db 48h

+    db 0c7h

+    db 0c0h

+    dd 21000h

+;   mov rax, 21000h

+    db 50h

+;   push rax

+

+; ret

+    db 0c3h

+

+Empty8042InputBuffer:

+        mov cx,0

+Empty8042Loop:

+        out     DELAY_PORT,ax               ; Delay 1us

+        in      al,KBD_STATUS_PORT          ; Read the 8042 Status Port

+        and     al,02h                      ; Check the Input Buffer Full Flag

+        loopnz  Empty8042Loop               ; Loop until the input buffer is empty or a timout of 65536 uS

+        ret

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+; data

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd 0                        ; (GDT base gets set above)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   global descriptor table (GDT)

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+        align 02h

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE          ; Selector [0x0]

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE          ; Selector [0x8]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE          ; Selector [0x10]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE          ; Selector [0x18]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE          ; Selector [0x20]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE          ; Selector [0x28]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+;

+; system data segment descriptor

+;

+SYS_DATA64_SEL    equ $-GDT_BASE          ; Selector [0x30]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0CFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+;

+; system code segment descriptor

+;

+SYS_CODE64_SEL    equ $-GDT_BASE          ; Selector [0x38]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; P | DPL [1..2] | 1   | 1   | C | R | A

+        db 0AFh         ; G | D   | L    | AVL | Segment [19..16]

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE            ; Selector [0x40]

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+        align 02h

+

+

+

+idtr            dw IDT_END - IDT_BASE - 1   ; IDT limit

+        dq 0                        ; (IDT base gets set above)

+

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+;   interrupt descriptor table (IDT)

+;

+;   Note: The hardware IRQ's specified in this table are the normal PC/AT IRQ

+;       mappings.  This implementation only uses the system timer and all other

+;       IRQs will remain masked.  The descriptors for vectors 33+ are provided

+;       for convenience.

+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

+

+;idt_tag db "IDT",0     

+        align 02h

+

+public IDT_BASE

+IDT_BASE:

+; divide by zero (INT 0)

+DIV_ZERO_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; debug exception (INT 1)

+DEBUG_EXCEPT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; NMI (INT 2)

+NMI_SEL             equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; soft breakpoint (INT 3)

+BREAKPOINT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; overflow (INT 4)

+OVERFLOW_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; bounds check (INT 5)

+BOUNDS_CHECK_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid opcode (INT 6)

+INVALID_OPCODE_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; device not available (INT 7)

+DEV_NOT_AVAIL_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; double fault (INT 8)

+DOUBLE_FAULT_SEL    equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Coprocessor segment overrun - reserved (INT 9)

+RSVD_INTR_SEL1      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; invalid TSS (INT 0ah)

+INVALID_TSS_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; segment not present (INT 0bh)

+SEG_NOT_PRESENT_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; stack fault (INT 0ch)

+STACK_FAULT_SEL     equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; general protection (INT 0dh)

+GP_FAULT_SEL        equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; page fault (INT 0eh)

+PAGE_FAULT_SEL      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Intel reserved - do not use (INT 0fh)

+RSVD_INTR_SEL2      equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; floating point error (INT 10h)

+FLT_POINT_ERR_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; alignment check (INT 11h)

+ALIGNMENT_CHECK_SEL equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; machine check (INT 12h)

+MACHINE_CHECK_SEL   equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; SIMD floating-point exception (INT 13h)

+SIMD_EXCEPTION_SEL  equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; 85 unspecified descriptors, First 12 of them are reserved, the rest are avail

+        db (85 * 16) dup(0)

+        

+; IRQ 0 (System timer) - (INT 68h)

+IRQ0_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 1 (8042 Keyboard controller) - (INT 69h)

+IRQ1_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; Reserved - IRQ 2 redirect (IRQ 2) - DO NOT USE!!! - (INT 6ah)

+IRQ2_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 3 (COM 2) - (INT 6bh)

+IRQ3_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 4 (COM 1) - (INT 6ch)

+IRQ4_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 5 (LPT 2) - (INT 6dh)

+IRQ5_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 6 (Floppy controller) - (INT 6eh)

+IRQ6_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 7 (LPT 1) - (INT 6fh)

+IRQ7_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 8 (RTC Alarm) - (INT 70h)

+IRQ8_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 9 - (INT 71h)

+IRQ9_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 10 - (INT 72h)

+IRQ10_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 11 - (INT 73h)

+IRQ11_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 12 (PS/2 mouse) - (INT 74h)

+IRQ12_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 13 (Floating point error) - (INT 75h)

+IRQ13_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 14 (Secondary IDE) - (INT 76h)

+IRQ14_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+; IRQ 15 (Primary IDE) - (INT 77h)

+IRQ15_SEL            equ $-IDT_BASE

+        dw 0            ; offset 15:0

+        dw SYS_CODE64_SEL ; selector 15:0

+        db 0            ; 0 for interrupt gate

+        db 0eh OR 80h   ; (10001110)type = 386 interrupt gate, present

+        dw 0            ; offset 31:16

+        dd 0            ; offset 63:32

+        dd 0            ; 0 for reserved

+

+IDT_END:

+

+        align 02h

+

+MemoryMapSize   dd  0

+MemoryMap   dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0

+

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+        dd  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+

+        org 0fe0h

+MyStack:    

+        ; below is the pieces of the IVT that is used to redirect INT 68h - 6fh

+        ;    back to INT 08h - 0fh  when in real mode...  It is 'org'ed to a

+        ;    known low address (20f00) so it can be set up by PlMapIrqToVect in

+        ;    8259.c

+                

+        int 8

+        iret

+        

+        int 9

+        iret

+        

+        int 10

+        iret

+        

+        int 11

+        iret

+        

+        int 12

+        iret

+        

+        int 13

+        iret

+        

+        int 14

+        iret

+        

+        int 15

+        iret

+        

+        

+        org 0ffeh

+BlockSignature:

+        dw  0aa55h

+

+        end 

diff --git a/uefi/linaro-edk2/DuetPkg/Contributions.txt b/uefi/linaro-edk2/DuetPkg/Contributions.txt
new file mode 100644
index 0000000..f87cbd7
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Contributions.txt
@@ -0,0 +1,218 @@
+

+======================

+= Code Contributions =

+======================

+

+To make a contribution to a TianoCore project, follow these steps.

+1. Create a change description in the format specified below to

+   use in the source control commit log.

+2. Your commit message must include your "Signed-off-by" signature,

+   and "Contributed-under" message.

+3. Your "Contributed-under" message explicitly states that the

+   contribution is made under the terms of the specified

+   contribution agreement.  Your "Contributed-under" message

+   must include the name of contribution agreement and version.

+   For example: Contributed-under: TianoCore Contribution Agreement 1.0

+   The "TianoCore Contribution Agreement" is included below in

+   this document.

+4. Submit your code to the TianoCore project using the process

+   that the project documents on its web page.  If the process is

+   not documented, then submit the code on development email list

+   for the project.

+5. It is preferred that contributions are submitted using the same

+   copyright license as the base project. When that is not possible,

+   then contributions using the following licenses can be accepted:

+   * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause

+   * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause

+   * MIT: http://opensource.org/licenses/MIT

+   * Python-2.0: http://opensource.org/licenses/Python-2.0

+   * Zlib: http://opensource.org/licenses/Zlib

+

+   Contributions of code put into the public domain can also be

+   accepted.

+

+   Contributions using other licenses might be accepted, but further

+   review will be required.

+

+=====================================================

+= Change Description / Commit Message / Patch Email =

+=====================================================

+

+Your change description should use the standard format for a

+commit message, and must include your "Signed-off-by" signature

+and the "Contributed-under" message.

+

+== Sample Change Description / Commit Message =

+

+=== Start of sample patch email message ===

+

+From: Contributor Name <contributor@example.com>

+Subject: [PATCH] CodeModule: Brief-single-line-summary

+

+Full-commit-message

+

+Contributed-under: TianoCore Contribution Agreement 1.0

+Signed-off-by: Contributor Name <contributor@example.com>

+---

+

+An extra message for the patch email which will not be considered part

+of the commit message can be added here.

+

+Patch content inline or attached

+

+=== End of sample patch email message ===

+

+=== Notes for sample patch email ===

+

+* The first line of commit message is taken from the email's subject

+  line following [PATCH]. The remaining portion of the commit message

+  is the email's content until the '---' line.

+* git format-patch is one way to create this format

+

+=== Definitions for sample patch email ===

+

+* "CodeModule" is a short idenfier for the affected code.  For

+  example MdePkg, or MdeModulePkg UsbBusDxe.

+* "Brief-single-line-summary" is a short summary of the change.

+* The entire first line should be less than ~70 characters.

+* "Full-commit-message" a verbose multiple line comment describing

+  the change.  Each line should be less than ~70 characters.

+* "Contributed-under" explicitely states that the contribution is

+  made under the terms of the contribtion agreement.  This

+  agreement is included below in this document.

+* "Signed-off-by" is the contributor's signature identifying them

+  by their real/legal name and their email address.

+

+========================================

+= TianoCore Contribution Agreement 1.0 =

+========================================

+

+INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION,

+INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE

+PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE

+TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE

+TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR

+REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE

+CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS

+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED

+BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS

+AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE

+AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT

+USE THE CONTENT.

+

+Unless otherwise indicated, all Content made available on the TianoCore

+site is provided to you under the terms and conditions of the BSD

+License ("BSD"). A copy of the BSD License is available at

+http://opensource.org/licenses/bsd-license.php

+or when applicable, in the associated License.txt file.

+

+Certain other content may be made available under other licenses as

+indicated in or with such Content. (For example, in a License.txt file.)

+

+You accept and agree to the following terms and conditions for Your

+present and future Contributions submitted to TianoCore site. Except

+for the license granted to Intel hereunder, You reserve all right,

+title, and interest in and to Your Contributions.

+

+== SECTION 1: Definitions ==

+* "You" or "Contributor" shall mean the copyright owner or legal

+  entity authorized by the copyright owner that is making a

+  Contribution hereunder. All other entities that control, are

+  controlled by, or are under common control with that entity are

+  considered to be a single Contributor. For the purposes of this

+  definition, "control" means (i) the power, direct or indirect, to

+  cause the direction or management of such entity, whether by

+  contract or otherwise, or (ii) ownership of fifty percent (50%)

+  or more of the outstanding shares, or (iii) beneficial ownership

+  of such entity.

+* "Contribution" shall mean any original work of authorship,

+  including any modifications or additions to an existing work,

+  that is intentionally submitted by You to the TinaoCore site for

+  inclusion in, or documentation of, any of the Content. For the

+  purposes of this definition, "submitted" means any form of

+  electronic, verbal, or written communication sent to the

+  TianoCore site or its representatives, including but not limited

+  to communication on electronic mailing lists, source code

+  control systems, and issue tracking systems that are managed by,

+  or on behalf of, the TianoCore site for the purpose of

+  discussing and improving the Content, but excluding

+  communication that is conspicuously marked or otherwise

+  designated in writing by You as "Not a Contribution."

+

+== SECTION 2: License for Contributions ==

+* Contributor hereby agrees that redistribution and use of the

+  Contribution in source and binary forms, with or without

+  modification, are permitted provided that the following

+  conditions are met:

+** Redistributions of source code must retain the Contributor's

+   copyright notice, this list of conditions and the following

+   disclaimer.

+** Redistributions in binary form must reproduce the Contributor's

+   copyright notice, this list of conditions and the following

+   disclaimer in the documentation and/or other materials provided

+   with the distribution.

+* Disclaimer. None of the names of Contributor, Intel, or the names

+  of their respective contributors may be used to endorse or

+  promote products derived from this software without specific

+  prior written permission.

+* Contributor grants a license (with the right to sublicense) under

+  claims of Contributor's patents that Contributor can license that

+  are infringed by the Contribution (as delivered by Contributor) to

+  make, use, distribute, sell, offer for sale, and import the

+  Contribution and derivative works thereof solely to the minimum

+  extent necessary for licensee to exercise the granted copyright

+  license; this patent license applies solely to those portions of

+  the Contribution that are unmodified. No hardware per se is

+  licensed.

+* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE

+  CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY

+  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,

+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A

+  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE

+  CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT

+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR

+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE

+  CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH

+  DAMAGE.

+

+== SECTION 3: Representations ==

+* You represent that You are legally entitled to grant the above

+  license. If your employer(s) has rights to intellectual property

+  that You create that includes Your Contributions, You represent

+  that You have received permission to make Contributions on behalf

+  of that employer, that Your employer has waived such rights for

+  Your Contributions.

+* You represent that each of Your Contributions is Your original

+  creation (see Section 4 for submissions on behalf of others).

+  You represent that Your Contribution submissions include complete

+  details of any third-party license or other restriction

+  (including, but not limited to, related patents and trademarks)

+  of which You are personally aware and which are associated with

+  any part of Your Contributions.

+

+== SECTION 4: Third Party Contributions ==

+* Should You wish to submit work that is not Your original creation,

+  You may submit it to TianoCore site separately from any

+  Contribution, identifying the complete details of its source

+  and of any license or other restriction (including, but not

+  limited to, related patents, trademarks, and license agreements)

+  of which You are personally aware, and conspicuously marking the

+  work as "Submitted on behalf of a third-party: [named here]".

+

+== SECTION 5: Miscellaneous ==

+* Applicable Laws. Any claims arising under or relating to this

+  Agreement shall be governed by the internal substantive laws of

+  the State of Delaware or federal courts located in Delaware,

+  without regard to principles of conflict of laws.

+* Language. This Agreement is in the English language only, which

+  language shall be controlling in all respects, and all versions

+  of this Agreement in any other language shall be for accommodation

+  only and shall not be binding. All communications and notices made

+  or given pursuant to this Agreement, and all documentation and

+  support to be provided, unless otherwise noted, shall be in the

+  English language.

+

diff --git a/uefi/linaro-edk2/DuetPkg/CreateBootDisk.bat b/uefi/linaro-edk2/DuetPkg/CreateBootDisk.bat
new file mode 100644
index 0000000..541de81
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/CreateBootDisk.bat
@@ -0,0 +1,146 @@
+@REM ## @file

+@REM #

+@REM #  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>

+@REM #

+@REM #  This program and the accompanying materials

+@REM #  are licensed and made available under the terms and conditions of the BSD License

+@REM #  which accompanies this distribution. The full text of the license may be found at

+@REM #  http://opensource.org/licenses/bsd-license.php

+@REM #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+@REM #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+@REM #

+@REM #

+@REM ##

+

+@REM Set up environment at first.

+

+@set BASETOOLS_DIR=%WORKSPACE_TOOLS_PATH%\Bin\Win32

+@set BOOTSECTOR_BIN_DIR=%WORKSPACE%\DuetPkg\BootSector\bin

+@set DISK_LABEL=DUET

+@set PROCESSOR=""

+@set STEP=1

+@call %WORKSPACE%\DuetPkg\GetVariables.bat

+

+@echo on

+

+@if "%1"=="" goto Help

+@if "%2"=="" goto Help

+@if "%3"=="" goto Help

+@if "%4"=="" goto Set_BootDisk

+@if "%4"=="step2" (@set STEP=2) else @set TARGET_ARCH=%4

+@if "%5"=="step2" @set STEP=2

+:Set_BootDisk

+@set EFI_BOOT_DISK=%2

+@if "%TARGET_ARCH%"=="IA32" set PROCESSOR=IA32

+@if "%TARGET_ARCH%"=="X64" set PROCESSOR=X64

+@if %PROCESSOR%=="" goto WrongArch

+@set BUILD_DIR=%WORKSPACE%\Build\DuetPkg%PROCESSOR%\%TARGET%_%TOOL_CHAIN_TAG%

+

+@if "%1"=="floppy" goto CreateFloppy

+@if "%1"=="file" goto CreateFile

+@if "%1"=="usb" goto CreateUsb

+@if "%1"=="ide" goto CreateIde

+

+goto Help

+

+:CreateFloppy

+@if NOT "%3"=="FAT12" goto WrongFATType

+@echo Start to create floppy boot disk ...

+@echo Format %EFI_BOOT_DISK% ...

+@echo.> FormatCommandInput.txt

+@echo.n>> FormatCommandInput.txt

+@format /v:%DISK_LABEL% /q %EFI_BOOT_DISK% < FormatCommandInput.txt > NUL

+@del FormatCommandInput.txt

+@echo Create boot sector ...

+@%BASETOOLS_DIR%\Genbootsector.exe -i %EFI_BOOT_DISK% -o FDBs.com

+@copy %BOOTSECTOR_BIN_DIR%\Bootsect.com FDBs-1.com

+@%BASETOOLS_DIR%\Bootsectimage.exe -g FDBs.com FDBs-1.com -f

+@REM @del FDBS.com

+@%BASETOOLS_DIR%\Genbootsector.exe -o %EFI_BOOT_DISK% -i FDBs-1.com 

+@del FDBs-1.com

+@echo Done.

+@copy %BUILD_DIR%\FV\EfiLdr %EFI_BOOT_DISK%

+@goto CreateBootFile

+

+:CreateFile

+@if NOT "%3"=="FAT12" goto WrongFATType

+@echo Start to create file boot disk ...

+@echo Create boot sector ...

+%BASETOOLS_DIR%\Genbootsector.exe -i %EFI_BOOT_DISK% -o FDBs.com

+@copy %BOOTSECTOR_BIN_DIR%\Bootsect.com FDBs-1.com

+@%BASETOOLS_DIR%\Bootsectimage.exe -g FDBs.com FDBs-1.com -f

+@REM @del FDBS.com

+@%BASETOOLS_DIR%\Genbootsector.exe -o %EFI_BOOT_DISK% -i FDBs-1.com 

+@del FDBs-1.com

+@echo Done.

+@goto end

+

+:CreateUsb

+@echo Start to create usb boot disk ...

+@if "%3"=="FAT16" goto CreateUsb_FAT16

+@if "%3"=="FAT32" goto CreateUsb_FAT32

+@if "%3"=="FAT12" goto WrongFATType

+

+:CreateUsb_FAT16

+@if "%STEP%"=="2" goto CreateUsb_FAT16_step2

+@echo Format %EFI_BOOT_DISK% ...

+@echo.> FormatCommandInput.txt

+@format /FS:FAT /v:%DISK_LABEL% /q %EFI_BOOT_DISK% < FormatCommandInput.txt > NUL

+@del FormatCommandInput.txt

+@echo Create boot sector ...

+@%BASETOOLS_DIR%\Genbootsector.exe -i %EFI_BOOT_DISK% -o UsbBs16.com

+@copy %BOOTSECTOR_BIN_DIR%\Bs16.com Bs16-1.com 

+@%BASETOOLS_DIR%\Bootsectimage.exe -g UsbBs16.com Bs16-1.com -f 

+@%BASETOOLS_DIR%\Genbootsector.exe -o %EFI_BOOT_DISK% -i Bs16-1.com

+@del Bs16-1.com

+@%BASETOOLS_DIR%\Genbootsector.exe -m -o %EFI_BOOT_DISK% -i %BOOTSECTOR_BIN_DIR%\Mbr.com

+@echo Done.

+@echo PLEASE UNPLUG USB, THEN PLUG IT AGAIN!

+@goto end

+

+:CreateUsb_FAT16_step2

+@copy %BUILD_DIR%\FV\EfiLdr16 %EFI_BOOT_DISK%

+@goto CreateBootFile

+

+:CreateUsb_FAT32

+@if "%STEP%"=="2" goto CreateUsb_FAT32_step2

+@echo Format %EFI_BOOT_DISK% ...

+@echo.> FormatCommandInput.txt

+@format /FS:FAT32 /v:%DISK_LABEL% /q %EFI_BOOT_DISK% < FormatCommandInput.txt > NUL

+@del FormatCommandInput.txt

+@echo Create boot sector ...

+@%BASETOOLS_DIR%\Genbootsector.exe -i %EFI_BOOT_DISK% -o UsbBs32.com

+@copy %BOOTSECTOR_BIN_DIR%\Bs32.com Bs32-1.com 

+@%BASETOOLS_DIR%\Bootsectimage.exe -g UsbBs32.com Bs32-1.com -f 

+@del UsbBs32.com

+@%BASETOOLS_DIR%\Genbootsector.exe -o %EFI_BOOT_DISK% -i Bs32-1.com

+@del Bs32-1.com

+@%BASETOOLS_DIR%\Genbootsector.exe -m -o %EFI_BOOT_DISK% -i %BOOTSECTOR_BIN_DIR%\Mbr.com

+@echo Done.

+@echo PLEASE UNPLUG USB, THEN PLUG IT AGAIN!

+@goto end  

+

+:CreateUsb_FAT32_step2

+@copy %BUILD_DIR%\FV\EfiLdr20 %EFI_BOOT_DISK%

+@goto CreateBootFile

+

+:CreateIde

+@goto end

+

+:CreateBootFile

+@mkdir %EFI_BOOT_DISK%\efi\boot

+copy %WORKSPACE%\ShellBinPkg\UefiShell\%PROCESSOR%\Shell.efi %EFI_BOOT_DISK%\efi\boot\boot%PROCESSOR%.efi /y

+@goto end

+

+:WrongFATType

+@echo Wrong FAT type %3 for %1

+@goto end

+

+:WrongArch

+@echo Error! Wrong architecture.

+@goto Help

+

+:Help

+@echo "Usage: CreateBootDisk [usb|floppy|ide] DiskNumber [FAT12|FAT16|FAT32] [IA32|X64]"

+:end

+@echo on

diff --git a/uefi/linaro-edk2/DuetPkg/CreateBootDisk.sh b/uefi/linaro-edk2/DuetPkg/CreateBootDisk.sh
new file mode 100755
index 0000000..f2ff571
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/CreateBootDisk.sh
@@ -0,0 +1,218 @@
+#! /bin/sh
+
+## @file
+#
+#  Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+# Set up environment at fisrt.
+
+if [ -z "$EDK_TOOLS_PATH" ]
+then
+export BASETOOLS_DIR=$WORKSPACE/Conf/BaseToolsSource/Source/C/bin
+else
+export BASETOOLS_DIR=$EDK_TOOLS_PATH/Source/C/bin
+fi
+
+export BOOTSECTOR_BIN_DIR=$WORKSPACE/DuetPkg/BootSector/bin
+export DISK_LABEL=DUET
+export PROCESS_MARK=TRUE
+
+if [ \
+     -z "$*" -o \
+     "$*" = "-?" -o \
+     "$*" = "-h" -o \
+     "$*" = "--help" \
+   ]
+then
+	echo "Usage: CreateBootDisk [usb|floppy|ide|file] MediaPath DevicePath [FAT12|FAT16|FAT32] [IA32|X64] [GCC44|UNIXGCC]"
+	echo "e.g. : CreateBootDisk floppy /media/floppy0 /dev/fd0 FAT12 IA32"
+	PROCESS_MARK=FALSE
+fi
+
+case "$5" in
+   IA32)
+     export PROCESSOR=IA32
+     ;;
+   X64)
+     export PROCESSOR=X64
+     ;;
+   *)
+     echo Invalid Architecture string, should be only IA32 or X64
+     return 1
+esac
+
+if [ -z "$6" ]
+then
+  TOOLCHAIN=GCC44
+else
+  TOOLCHAIN=$6
+fi
+
+export BUILD_DIR=$WORKSPACE/Build/DuetPkg$PROCESSOR/DEBUG_$TOOLCHAIN
+
+
+export EFI_BOOT_MEDIA=$2
+export EFI_BOOT_DEVICE=$3
+
+if [ "$PROCESS_MARK" = TRUE ]
+then
+	case "$1" in
+		floppy)
+			if [ "$4" = FAT12 ]
+			then
+				echo Start to create floppy boot disk ...
+				echo Format $EFI_BOOT_MEDIA ...
+				## Format floppy disk
+				umount $EFI_BOOT_MEDIA
+				mkfs.msdos $EFI_BOOT_DEVICE
+				mount $EFI_BOOT_DEVICE $EFI_BOOT_MEDIA
+				echo Create boot sector ...
+				## Linux version of GenBootSector has not pass build yet.
+				$BASETOOLS_DIR/GnuGenBootSector -i $EFI_BOOT_DEVICE -o FDBs.com
+				cp $BOOTSECTOR_BIN_DIR/bootsect.com FDBs-1.com
+				$BASETOOLS_DIR/BootSectImage -g FDBs.com FDBs-1.com -f
+				$BASETOOLS_DIR/GnuGenBootSector -o $EFI_BOOT_DEVICE -i FDBs-1.com
+				rm FDBs-1.com
+				cp $BUILD_DIR/FV/Efildr $EFI_BOOT_MEDIA
+	
+				mkdir -p $EFI_BOOT_MEDIA/efi
+				mkdir -p $EFI_BOOT_MEDIA/efi/boot
+				if [ "$5" = IA32 ]
+				then
+					cp $WORKSPACE/ShellBinPkg/UefiShell/Ia32/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+				else
+					if [ "$5" = X64 ]
+					then
+						cp $WORKSPACE/ShellBinPkg/UefiShell/X64/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+					else
+						echo Wrong Arch!
+					fi
+				fi
+				echo Done.
+			else
+				echo "Wrong FAT type $4 for floppy!"
+			fi
+			;;
+
+		file) # CreateFile
+			if [ "$4" = FAT12 ]
+				then
+				echo "Start to create file boot disk ..."
+				dd bs=512 count=2880 if=/dev/zero of=$EFI_BOOT_MEDIA
+				mkfs.msdos -F 12 $EFI_BOOT_MEDIA
+
+				mcopy -i $EFI_BOOT_MEDIA $BUILD_DIR/FV/Efildr ::/Efildr
+				mmd -i $EFI_BOOT_MEDIA ::/efi ::/efi/boot
+				if [ "$5" = IA32 ]
+				then
+					mcopy -i $EFI_BOOT_MEDIA $WORKSPACE/ShellBinPkg/UefiShell/Ia32/Shell.efi ::/efi/boot/boot$5.efi
+				elif [ "$5" = X64 ]
+				then
+					mcopy -i $EFI_BOOT_MEDIA $WORKSPACE/ShellBinPkg/UefiShell/X64/Shell.efi ::/efi/boot/boot$5.efi
+				else
+					echo Wrong Arch!
+				fi
+				mdir -i $EFI_BOOT_MEDIA -s ::
+
+				## Linux version of GenBootSector has not pass build yet.
+				$BASETOOLS_DIR/GnuGenBootSector -i $EFI_BOOT_MEDIA -o $EFI_BOOT_MEDIA.bs0
+				cp $BOOTSECTOR_BIN_DIR/bootsect.com $EFI_BOOT_MEDIA.bs1
+				$BASETOOLS_DIR/BootSectImage -g $EFI_BOOT_MEDIA.bs0 $EFI_BOOT_MEDIA.bs1
+				$BASETOOLS_DIR/GnuGenBootSector -o $EFI_BOOT_MEDIA -i $EFI_BOOT_MEDIA.bs1
+				rm $EFI_BOOT_MEDIA.bs[0-1]
+				echo Done.
+			else
+				echo "Wrong FAT type" $4 "for floppy!"
+			fi
+			;;
+
+		usb) # CreateUsb
+
+			if [ "$4" = FAT16 ]
+			then
+				if [ "$6" = step2 ]
+				then
+					cp $BUILD_DIR/FV/Efildr16 $EFI_BOOT_MEDIA
+					mkdir $EFI_BOOT_MEDIA/efi/boot
+					if [ "$5" = IA32 ]
+					then
+						cp $WORKSPACE/ShellBinPkg/UefiShell/Ia32/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+					else
+						if [ "$5" = X64 ]
+						then
+							cp $WORKSPACE/ShellBinPkg/UefiShell/X64/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+						else
+							echo Wrong Arch!
+						fi
+					fi
+					echo "step2 Done!"
+				else
+					echo Format $EFI_BOOT_DEVICE ...
+					#Do format command.
+					echo Create boot sector ...
+					## Linux version of GenBootSector & Bootsectimage has not pass build yet.
+					$BASETOOLS_DIR/GnuGenBootSector -i $EFI_BOOT_DEVICE -o UsbBs16.com
+					cp $BOOTSECTOR_BIN_DIR/bs16.com Bs16-1.com
+					$BASETOOLS_DIR/BootSectImage -g UsbBs16.com Bs16-1.com -f
+					$BASETOOLS_DIR/GnuGenBootSector -o $EFI_BOOT_DEVICE -i Bs16-1.com
+					rm Bs16-1.com
+					$BASETOOLS_DIR/GnuGenBootSector -m -o $EFI_BOOT_DEVICE -i $BOOTSECTOR_BIN_DIR/Mbr.com
+					echo Done.
+					echo PLEASE UNPLUG USB, THEN PLUG IT AGAIN TO DO STEP2!
+				fi
+			elif [ "$4" = FAT32 ]
+			then 
+				if [ "$6" = step2 ]
+				then
+					cp $BUILD_DIR/FV/Efildr20 $EFI_BOOT_MEDIA
+					mkdir $EFI_BOOT_MEDIA/efi/boot
+					if [ "$5" = IA32 ]
+					then
+						cp $WORKSPACE/ShellBinPkg/UefiShell/Ia32/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+					else
+						if [ "$5" = X64 ]
+						then
+							cp $WORKSPACE/ShellBinPkg/UefiShell/X64/Shell.efi $EFI_BOOT_MEDIA/efi/boot/boot$5.efi
+						else
+							echo Wrong Arch!
+						fi
+					fi
+					echo "step2 Done!"
+				else
+					echo Format $EFI_BOOT_DEVICE ...
+					#Do format command.
+					echo Create boot sector ...
+					## Linux version of GenBootSector & Bootsectimage has not pass build yet.
+					$BASETOOLS_DIR/GnuGenBootSector -i $EFI_BOOT_DEVICE -o UsbBs32.com
+					cp $BOOTSECTOR_BIN_DIR/bs32.com Bs32-1.com
+					$BASETOOLS_DIR/BootSectImage -g UsbBs32.com Bs32-1.com -f
+					$BASETOOLS_DIR/GnuGenBootSector -o $EFI_BOOT_DEVICE -i Bs32-1.com
+					rm Bs32-1.com
+					$BASETOOLS_DIR/GnuGenBootSector -m -o $EFI_BOOT_DEVICE -i $BOOTSECTOR_BIN_DIR/Mbr.com
+					echo Done.
+					echo PLEASE UNPLUG USB, THEN PLUG IT AGAIN TO DO STEP2!
+				fi			
+			else
+				echo "Wrong FAT type $1 for floppy!"
+			fi
+	
+			;;
+
+		ide) # CreateIde
+		echo "Not support yet!"
+		;;
+		*)
+		echo "Arg1 should be [floppy | file | usb | ide] !"
+
+	esac
+fi
diff --git a/uefi/linaro-edk2/DuetPkg/DuetPkg.dec b/uefi/linaro-edk2/DuetPkg/DuetPkg.dec
new file mode 100644
index 0000000..0958af3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DuetPkg.dec
@@ -0,0 +1,42 @@
+## @file 

+#

+# This Package provides all definitions(including functions, MACROs, structures and library classes)

+# and libraries instances, which are only used by Duet platform.

+#

+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>

+#

+# This program and the accompanying materials are licensed and made available under

+# the terms and conditions of the BSD License which accompanies this distribution.

+# The full text of the license may be found at

+# http://opensource.org/licenses/bsd-license.php

+#

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+##

+

+[Defines]

+  DEC_SPECIFICATION              = 0x00010005

+  PACKAGE_NAME                   = DuetPkg

+  PACKAGE_GUID                   = 151B568B-B390-4cf1-ABD6-228E0AB96F57

+  PACKAGE_VERSION                = 0.4

+

+[Includes]

+  Include

+

+[Guids]

+  gEfiPciExpressBaseAddressGuid = {0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0 }}

+  gEfiAcpiDescriptionGuid       = {0x3c699197, 0x093c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9 }}

+  gEfiFlashMapHobGuid           = { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 }}

+  

+  ## Include/Guid/PciOptionRomTable.h

+  gEfiPciOptionRomTableGuid     = { 0x7462660F, 0x1CBD, 0x48DA, { 0xAD, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1C }}

+

+  ## Include/Guid/ConsoleOutConfig.h

+  gDuetConsoleOutConfigGuid     = { 0xED150714, 0xDF30, 0x407D, { 0xB2, 0x4A, 0x4B, 0x74, 0x2F, 0xD5, 0xCE, 0xA2 }}

+  

+  ## Include/Guid/DxeCoreFileName.h

+  gDxeCoreFileNameGuid          = { 0xD6A2CB7F, 0x6A18, 0x4e2f, { 0xB4, 0x3B, 0x99, 0x20, 0xA7, 0x33, 0x70, 0x0A }}

+

+  ## Include/Guid/LdrMemoryDescriptor.h

+  gLdrMemoryDescriptorGuid      = { 0x7701d7e5, 0x7d1d, 0x4432, { 0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }}

diff --git a/uefi/linaro-edk2/DuetPkg/DuetPkg.fdf b/uefi/linaro-edk2/DuetPkg/DuetPkg.fdf
new file mode 100644
index 0000000..66f8b68
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DuetPkg.fdf
@@ -0,0 +1,151 @@
+## @file

+# This is DUET FDF file with UEFI HII features enabled

+#

+# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>

+#

+#    This program and the accompanying materials

+#    are licensed and made available under the terms and conditions of the BSD License

+#    which accompanies this distribution. The full text of the license may be found at

+#    http://opensource.org/licenses/bsd-license.php

+#

+#    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+

+################################################################################

+#

+# FV Section

+#

+# [FV] section is used to define what components or modules are placed within a flash

+# device file.  This section also defines order the components and modules are positioned

+# within the image.  The [FV] section consists of define statements, set statements and

+# module statements.

+#

+################################################################################

+[FV.DuetEfiMainFv]

+BlockSize          = 0x10000

+FvAlignment        = 16         #FV alignment and FV attributes setting.

+ERASE_POLARITY     = 1

+MEMORY_MAPPED      = TRUE

+STICKY_WRITE       = TRUE

+LOCK_CAP           = TRUE

+LOCK_STATUS        = TRUE

+WRITE_DISABLED_CAP = TRUE

+WRITE_ENABLED_CAP  = TRUE

+WRITE_STATUS       = TRUE

+WRITE_LOCK_CAP     = TRUE

+WRITE_LOCK_STATUS  = TRUE

+READ_DISABLED_CAP  = TRUE

+READ_ENABLED_CAP   = TRUE

+READ_STATUS        = TRUE

+READ_LOCK_CAP      = TRUE

+READ_LOCK_STATUS   = TRUE

+

+APRIORI DXE {

+  INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

+  INF  PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf

+}

+

+INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

+INF  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf

+INF  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf

+INF  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf

+

+INF  DuetPkg/FSVariable/FSVariable.inf

+INF  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf

+INF  MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf

+INF  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf

+INF  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf

+INF  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf

+INF  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf

+INF  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf

+INF  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf

+

+INF  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf

+INF  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf

+INF  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf

+INF  DuetPkg/SmbiosGenDxe/SmbiosGen.inf

+#INF  DuetPkg/FvbRuntimeService/DUETFwh.inf

+INF  IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf

+INF  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf

+INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf

+INF  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf

+INF  UefiCpuPkg/CpuDxe/CpuDxe.inf

+

+INF  PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf

+INF  DuetPkg/AcpiResetDxe/Reset.inf

+INF  DuetPkg/LegacyMetronome/Metronome.inf

+INF  PcAtChipsetPkg/8254TimerDxe/8254Timer.inf

+INF  PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

+INF  DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf

+INF  DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf

+INF  IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf

+INF  IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf

+

+  # IDE/AHCI Support

+INF  DuetPkg/SataControllerDxe/SataControllerDxe.inf

+INF  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf

+INF  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf

+INF  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf

+INF  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf

+

+  # Usb Support

+INF  MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf

+INF  MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf

+INF  MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf

+INF  MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf

+INF  MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf

+

+  # ISA Support

+INF  PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf

+INF  IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf

+INF  IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf

+INF  IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf

+INF  IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf

+

+INF  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf

+INF  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf

+INF  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf

+INF  DuetPkg/BiosVideoThunkDxe/BiosVideo.inf

+

+  # Binary INF file to support toggle among different CPU architectures.

+INF  RuleOverride=BINARY FatBinPkg/EnhancedFatDxe/Fat.inf

+

+FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) {

+    SECTION RAW = MdeModulePkg/Logo/Logo.bmp

+  }

+

+[Rule.Common.DXE_CORE]

+  FILE DXE_CORE = $(NAMED_GUID) {

+      PE32     PE32           $(INF_OUTPUT)/$(MODULE_NAME).efi

+  }

+

+[Rule.Common.UEFI_DRIVER]

+  FILE DRIVER = $(NAMED_GUID) {

+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex

+        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+  }

+

+[Rule.Common.DXE_DRIVER]

+  FILE DRIVER = $(NAMED_GUID) {

+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex

+        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+  }

+

+[Rule.Common.DXE_RUNTIME_DRIVER]

+  FILE DRIVER = $(NAMED_GUID) {

+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex

+        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+  }

+

+[Rule.Common.UEFI_APPLICATION]

+  FILE APPLICATION = $(NAMED_GUID) {

+        PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi

+  }

+

+[Rule.Common.UEFI_DRIVER.BINARY]

+  FILE DRIVER = $(NAMED_GUID) {

+    DXE_DEPEX    DXE_DEPEX Optional      |.depex

+        PE32     PE32                    |.efi

+  }

+

diff --git a/uefi/linaro-edk2/DuetPkg/DuetPkgIa32.dsc b/uefi/linaro-edk2/DuetPkg/DuetPkgIa32.dsc
new file mode 100644
index 0000000..db1f7b6
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DuetPkgIa32.dsc
@@ -0,0 +1,272 @@
+## @file

+#  An EFI/Framework Emulation Platform with UEFI HII interface supported.

+#

+#  Developer's UEFI Emulation. DUET provides an EFI/UEFI IA32/X64 environment on legacy BIOS,

+#  to help developing and debugging native EFI/UEFI drivers.

+#

+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+##

+

+################################################################################

+#

+# Defines Section - statements that will be processed to create a Makefile.

+#

+################################################################################

+[Defines]

+  PLATFORM_NAME                  = DuetPkg

+  PLATFORM_GUID                  = 199E24E0-0989-42aa-87F2-611A8C397E72

+  PLATFORM_VERSION               = 0.4

+  DSC_SPECIFICATION              = 0x00010005

+  OUTPUT_DIRECTORY               = Build/DuetPkgIA32

+  SUPPORTED_ARCHITECTURES        = IA32

+  BUILD_TARGETS                  = DEBUG

+  SKUID_IDENTIFIER               = DEFAULT

+  FLASH_DEFINITION               = DuetPkg/DuetPkg.fdf

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this Platform.

+#

+################################################################################

+[LibraryClasses]

+  #

+  # Entry point

+  #

+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf

+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf

+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf

+  #

+  # Basic

+  #

+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf

+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf

+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf

+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf

+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf

+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf

+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf

+  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf

+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf

+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf

+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf

+  #

+  # UEFI & PI

+  #

+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf

+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf

+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf

+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf

+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf

+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf

+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf

+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf

+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf

+

+  #

+  # Generic Modules

+  #

+  UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf

+  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf

+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf

+  GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf

+  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf

+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf

+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf

+  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf

+  #

+  # Platform

+  #

+  PlatformBdsLib|DuetPkg/Library/DuetBdsLib/PlatformBds.inf

+  TimerLib|DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf

+  #

+  # Misc

+  #

+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf

+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf

+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf

+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf

+  PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf

+  SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf

+  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf

+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf

+  LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf

+

+  #

+  # To save size, use NULL library for DebugLib and ReportStatusCodeLib.

+  # If need status code output, do library instance overriden as below DxeMain.inf does

+  #

+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf

+  ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf

+

+[LibraryClasses.common.DXE_CORE]

+  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf

+  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf

+

+################################################################################

+#

+# Pcd Section - list of all EDK II PCD Entries defined by this Platform

+#

+################################################################################

+[PcdsFixedAtBuild]

+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0

+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0

+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x0

+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE

+

+[PcdsFeatureFlag]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE

+

+###################################################################################################

+#

+# Components Section - list of the modules and components that will be processed by compilation

+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.

+#

+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed

+#       into firmware volume images. This section is just a list of modules to compile from

+#       source into UEFI-compliant binaries.

+#       It is the FDF file that contains information on combining binary files into firmware

+#       volume images, whose concept is beyond UEFI and is described in PI specification.

+#       Binary modules do not need to be listed in this section, as they should be

+#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),

+#       Logo (Logo.bmp), and etc.

+#       There may also be modules listed in this section that are not required in the FDF file,

+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be

+#       generated for it, but the binary will not be put into any firmware volume.

+#

+###################################################################################################

+[Components]

+  DuetPkg/DxeIpl/DxeIpl.inf {

+    <LibraryClasses>

+      #

+      # If no following overriden for ReportStatusCodeLib library class,

+      # All other module can *not* output debug information even they are use not NULL library

+      # instance for DebugLib and ReportStatusCodeLib

+      #

+      ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf

+  }

+

+  MdeModulePkg/Core/Dxe/DxeMain.inf {

+    #

+    # Enable debug output for DxeCore module, this is a sample for how to enable debug output

+    # for a module. If need turn on debug output for other module, please copy following overriden

+    # PCD and library instance to other module's override section.

+    #

+    <PcdsFixedAtBuild>

+      gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07

+      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F

+      gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000042

+    <LibraryClasses>

+      DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf

+      ReportStatusCodeLib|DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeCoreReportStatusCodeLibFromHob.inf

+  }

+

+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf

+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf

+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf

+

+  DuetPkg/FSVariable/FSVariable.inf

+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf

+  MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf

+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf

+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf

+  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf {

+    <LibraryClasses>

+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf

+  }

+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf

+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf

+  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf

+

+  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf

+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf

+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf

+  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf

+

+

+  DuetPkg/SmbiosGenDxe/SmbiosGen.inf

+  #DuetPkg/FvbRuntimeService/DUETFwh.inf

+  DuetPkg/EfiLdr/EfiLdr.inf {

+    <LibraryClasses>

+      DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+      NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf

+  }

+  IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf {

+    <LibraryClasses>

+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf

+  }

+  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf

+  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf

+  UefiCpuPkg/CpuDxe/CpuDxe.inf

+  PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf

+  DuetPkg/AcpiResetDxe/Reset.inf

+  DuetPkg/LegacyMetronome/Metronome.inf

+

+  PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

+  PcAtChipsetPkg/8254TimerDxe/8254Timer.inf

+  DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf

+  DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf

+  IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf

+  IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf

+

+  # IDE/AHCI Support

+  DuetPkg/SataControllerDxe/SataControllerDxe.inf

+  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf

+  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf

+  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf

+  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf

+

+  # Usb Support

+  MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf

+  MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf

+  MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf

+  MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf

+  MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf

+

+  # ISA Support

+  PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf

+

+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf

+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf

+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf

+

+  # Bios Thunk

+  DuetPkg/BiosVideoThunkDxe/BiosVideo.inf

+

+  #

+  # Sample Application

+  #

+  MdeModulePkg/Application/HelloWorld/HelloWorld.inf

+

+###################################################################################################

+#

+# BuildOptions Section - Define the module specific tool chain flags that should be used as

+#                        the default flags for a module. These flags are appended to any

+#                        standard flags that are defined by the build process. They can be

+#                        applied for any modules or only those modules with the specific

+#                        module style (EDK or EDKII) specified in [Components] section.

+#

+###################################################################################################

+[BuildOptions]

+  MSFT:*_*_*_CC_FLAGS = /FAsc /FR$(@R).SBR

+

diff --git a/uefi/linaro-edk2/DuetPkg/DuetPkgX64.dsc b/uefi/linaro-edk2/DuetPkg/DuetPkgX64.dsc
new file mode 100644
index 0000000..eeae767
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DuetPkgX64.dsc
@@ -0,0 +1,273 @@
+## @file

+#  An EFI/Framework Emulation Platform with UEFI HII interface supported.

+#

+#  Developer's UEFI Emulation. DUET provides an EFI/UEFI IA32/X64 environment on legacy BIOS,

+#  to help developing and debugging native EFI/UEFI drivers.

+#

+#  Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+##

+

+################################################################################

+#

+# Defines Section - statements that will be processed to create a Makefile.

+#

+################################################################################

+[Defines]

+  PLATFORM_NAME                  = DuetPkg

+  PLATFORM_GUID                  = 199E24E0-0989-42aa-87F2-611A8C397E72

+  PLATFORM_VERSION               = 0.4

+  DSC_SPECIFICATION              = 0x00010005

+  OUTPUT_DIRECTORY               = Build/DuetPkgX64

+  SUPPORTED_ARCHITECTURES        = X64

+  BUILD_TARGETS                  = DEBUG

+  SKUID_IDENTIFIER               = DEFAULT

+  FLASH_DEFINITION               = DuetPkg/DuetPkg.fdf

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this Platform.

+#

+################################################################################

+[LibraryClasses]

+  #

+  # Entry point

+  #

+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf

+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf

+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf

+  #

+  # Basic

+  #

+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf

+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf

+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf

+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf

+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf

+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf

+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf

+  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf

+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf

+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf

+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf

+  #

+  # UEFI & PI

+  #

+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf

+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf

+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf

+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf

+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf

+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf

+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf

+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf

+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf

+

+  #

+  # Generic Modules

+  #

+  UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf

+  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf

+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf

+  GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf

+  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf

+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf

+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf

+  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf

+  #

+  # Platform

+  #

+  PlatformBdsLib|DuetPkg/Library/DuetBdsLib/PlatformBds.inf

+  TimerLib|DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf

+  #

+  # Misc

+  #

+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf

+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf

+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf

+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf

+  PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf

+  SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf

+  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf

+  LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf

+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf

+  LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf

+

+  #

+  # To save size, use NULL library for DebugLib and ReportStatusCodeLib.

+  # If need status code output, do library instance overriden as below DxeMain.inf does

+  #

+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf

+  ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf

+

+[LibraryClasses.common.DXE_CORE]

+  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf

+  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf

+

+################################################################################

+#

+# Pcd Section - list of all EDK II PCD Entries defined by this Platform

+#

+################################################################################

+[PcdsFixedAtBuild]

+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0

+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0

+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x0

+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE

+

+[PcdsFeatureFlag]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE

+

+###################################################################################################

+#

+# Components Section - list of the modules and components that will be processed by compilation

+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.

+#

+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed

+#       into firmware volume images. This section is just a list of modules to compile from

+#       source into UEFI-compliant binaries.

+#       It is the FDF file that contains information on combining binary files into firmware

+#       volume images, whose concept is beyond UEFI and is described in PI specification.

+#       Binary modules do not need to be listed in this section, as they should be

+#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),

+#       Logo (Logo.bmp), and etc.

+#       There may also be modules listed in this section that are not required in the FDF file,

+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be

+#       generated for it, but the binary will not be put into any firmware volume.

+#

+###################################################################################################

+[Components]

+  DuetPkg/DxeIpl/DxeIpl.inf {

+    <LibraryClasses>

+      #

+      # If no following overriden for ReportStatusCodeLib library class,

+      # All other module can *not* output debug information even they are use not NULL library

+      # instance for DebugLib and ReportStatusCodeLib

+      #

+      ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf

+  }

+

+  MdeModulePkg/Core/Dxe/DxeMain.inf {

+    #

+    # Enable debug output for DxeCore module, this is a sample for how to enable debug output

+    # for a module. If need turn on debug output for other module, please copy following overriden

+    # PCD and library instance to other module's override section.

+    #

+    <PcdsFixedAtBuild>

+      gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07

+      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F

+      gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000042

+    <LibraryClasses>

+      DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf

+      ReportStatusCodeLib|DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeCoreReportStatusCodeLibFromHob.inf

+  }

+

+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf

+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf

+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf

+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf

+

+  DuetPkg/FSVariable/FSVariable.inf

+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf

+  MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf

+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf

+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf

+  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf {

+    <LibraryClasses>

+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf

+  }

+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf

+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf

+  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf

+

+  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf

+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf

+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf

+  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf

+

+

+  DuetPkg/SmbiosGenDxe/SmbiosGen.inf

+  #DuetPkg/FvbRuntimeService/DUETFwh.inf

+  DuetPkg/EfiLdr/EfiLdr.inf {

+    <LibraryClasses>

+      DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+      NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf

+  }

+  IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf {

+    <LibraryClasses>

+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf

+  }

+  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf

+  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf

+  UefiCpuPkg/CpuDxe/CpuDxe.inf

+  PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf

+  DuetPkg/AcpiResetDxe/Reset.inf

+  DuetPkg/LegacyMetronome/Metronome.inf

+

+  PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

+  PcAtChipsetPkg/8254TimerDxe/8254Timer.inf

+  DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf

+  DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf

+  IntelFrameworkModulePkg/Bus/Pci/VgaMiniPortDxe/VgaMiniPortDxe.inf

+  IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf

+

+  # IDE/AHCI Support

+  DuetPkg/SataControllerDxe/SataControllerDxe.inf

+  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf

+  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf

+  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf

+  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf

+

+  # Usb Support

+  MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf

+  MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf

+  MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf

+  MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf

+  MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf

+

+  # ISA Support

+  PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf

+  IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppyDxe.inf

+

+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf

+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf

+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf

+

+  # Bios Thunk

+  DuetPkg/BiosVideoThunkDxe/BiosVideo.inf

+

+  #

+  # Sample Application

+  #

+  MdeModulePkg/Application/HelloWorld/HelloWorld.inf

+

+###################################################################################################

+#

+# BuildOptions Section - Define the module specific tool chain flags that should be used as

+#                        the default flags for a module. These flags are appended to any

+#                        standard flags that are defined by the build process. They can be

+#                        applied for any modules or only those modules with the specific

+#                        module style (EDK or EDKII) specified in [Components] section.

+#

+###################################################################################################

+[BuildOptions]

+  MSFT:*_*_*_CC_FLAGS = /FAsc /FR$(@R).SBR

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.c
new file mode 100644
index 0000000..1cb7e39
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.c
@@ -0,0 +1,82 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Debug.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include "DxeIpl.h"

+#include <Library/SerialPortLib.h>

+#include "SerialStatusCode.h"

+#include "Debug.h"

+

+UINT8 *mCursor;

+UINT8 mHeaderIndex = 10;

+

+

+VOID

+PrintHeader (

+  CHAR8 Char

+  )

+{

+  *(UINT8 *)(UINTN)(0x000b8000 + mHeaderIndex) = Char;

+  mHeaderIndex += 2;

+}

+

+VOID

+ClearScreen (

+  VOID

+  )

+{

+  UINT32 Index;

+

+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);

+  for (Index = 0; Index < 80 * 49; Index++) {

+    *mCursor = ' ';

+    mCursor += 2;

+  }

+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);

+}

+

+VOID

+PrintString (

+  IN CONST CHAR8  *FormatString,

+  ...

+  )

+{

+  UINTN           Index;

+  CHAR8           PrintBuffer[1000];

+  VA_LIST         Marker;

+

+  VA_START (Marker, FormatString);

+  AsciiVSPrint (PrintBuffer, sizeof (PrintBuffer), FormatString, Marker);

+  VA_END (Marker);

+

+  for (Index = 0; PrintBuffer[Index] != 0; Index++) {

+    if (PrintBuffer[Index] == '\n') {

+      mCursor = (UINT8 *) (UINTN) (0xb8000 + (((((UINTN)mCursor - 0xb8000) + 160) / 160) * 160));

+    } else {

+      *mCursor = (UINT8) PrintBuffer[Index];

+      mCursor += 2;

+    }

+  }

+

+  //

+  // All information also output to serial port.

+  //

+  SerialPortWrite ((UINT8 *) PrintBuffer, Index);

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.h
new file mode 100644
index 0000000..7fcad26
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/Debug.h
@@ -0,0 +1,40 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Debug.h

+

+Abstract:

+

+Revision History:

+

+**/

+

+#ifndef _EFILDR_DEBUG_H_

+#define _EFILDR_DEBUG_H_

+

+VOID

+PrintHeader (

+  CHAR8 Char

+  );

+

+VOID

+PrintString (

+  IN CONST CHAR8  *FormatString,

+  ...

+  );

+

+VOID 

+ClearScreen (

+  VOID

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeInit.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeInit.c
new file mode 100644
index 0000000..b9a40a8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeInit.c
@@ -0,0 +1,278 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  DxeInit.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include "DxeIpl.h"

+

+#include "LegacyTable.h"

+#include "HobGeneration.h"

+#include "PpisNeededByDxeCore.h"

+#include "Debug.h"

+

+/*

+--------------------------------------------------------

+ Memory Map: (XX=32,64)

+--------------------------------------------------------

+0x0

+        IVT

+0x400

+        BDA

+0x500

+

+0x7C00

+        BootSector

+0x10000

+        EfiLdr (relocate by efiXX.COM)

+0x15000

+        Efivar.bin (Load by StartXX.COM)

+0x20000

+        StartXX.COM (E820 table, Temporary GDT, Temporary IDT)

+0x21000

+        EfiXX.COM (Temporary Interrupt Handler)

+0x22000

+        EfiLdr.efi + DxeIpl.Z + DxeMain.Z + BFV.Z

+0x86000

+        MemoryFreeUnder1M (For legacy driver DMA)

+0x90000

+        Temporary 4G PageTable for X64 (6 page)

+0x9F800

+        EBDA

+0xA0000

+        VGA

+0xC0000

+        OPROM

+0xE0000

+        FIRMEWARE

+0x100000 (1M)

+        Temporary Stack (1M)

+0x200000

+

+MemoryAbove1MB.PhysicalStart <-----------------------------------------------------+

+        ...                                                                        |

+        ...                                                                        |

+                        <- Phit.EfiMemoryBottom -------------------+               |

+        HOB                                                        |               |

+                        <- Phit.EfiFreeMemoryBottom                |               |

+                                                                   |     MemoryFreeAbove1MB.ResourceLength

+                        <- Phit.EfiFreeMemoryTop ------+           |               |

+        MemoryDescriptor (For ACPINVS, ACPIReclaim)    |    4M = CONSUMED_MEMORY   |

+                                                       |           |               |

+        Permament 4G PageTable for IA32 or      MemoryAllocation   |               |

+        Permament 64G PageTable for X64                |           |               |

+                        <------------------------------+           |               |

+        Permament Stack (0x20 Pages = 128K)                        |               |

+                        <- Phit.EfiMemoryTop ----------+-----------+---------------+

+        NvFV (64K)                                                                 |

+                                                                                 MMIO

+        FtwFV (128K)                                                               |  

+                        <----------------------------------------------------------+<---------+

+        DxeCore                                                                    |          |

+                                                                                DxeCore       |

+        DxeIpl                                                                     |   Allocated in EfiLdr

+                        <----------------------------------------------------------+          |

+        BFV                                                                      MMIO         |

+                        <- Top of Free Memory reported by E820 --------------------+<---------+

+        ACPINVS        or

+        ACPIReclaim    or

+        Reserved

+                        <- Memory Top on RealMemory

+

+0x100000000 (4G)

+

+MemoryFreeAbove4G.Physicalstart <--------------------------------------------------+

+                                                                                   |

+                                                                                   |

+                                                                  MemoryFreeAbove4GB.ResourceLength

+                                                                                   |

+                                                                                   |

+                                <--------------------------------------------------+

+*/

+

+VOID

+EnterDxeMain (

+  IN VOID *StackTop,

+  IN VOID *DxeCoreEntryPoint,

+  IN VOID *Hob,

+  IN VOID *PageTable

+  );

+

+VOID

+DxeInit (

+  IN EFILDRHANDOFF  *Handoff

+  )

+/*++

+

+  Routine Description:

+

+    This is the entry point after this code has been loaded into memory. 

+

+Arguments:

+

+

+Returns:

+

+    Calls into EFI Firmware

+

+--*/

+{

+  VOID                  *StackTop;

+  VOID                  *StackBottom;

+  VOID                  *PageTableBase;

+  VOID                  *MemoryTopOnDescriptor;

+  VOID                  *MemoryDescriptor;

+  VOID                  *NvStorageBase;

+  EFILDRHANDOFF         HandoffCopy;

+

+  CopyMem ((VOID*) &HandoffCopy, (VOID*) Handoff, sizeof (EFILDRHANDOFF));

+  Handoff = &HandoffCopy;

+

+  ClearScreen();

+

+  PrintString (

+    "Enter DxeIpl ...\n"

+    "Handoff:\n"

+    "Handoff.BfvBase = %p, BfvLength = %x\n"

+    "Handoff.DxeIplImageBase = %p, DxeIplImageSize = %x\n"

+    "Handoff.DxeCoreImageBase = %p, DxeCoreImageSize = %x\n",

+    Handoff->BfvBase, Handoff->BfvSize,

+    Handoff->DxeIplImageBase, Handoff->DxeIplImageSize,

+    Handoff->DxeCoreImageBase, Handoff->DxeCoreImageSize

+    );

+

+  //

+  // Hob Generation Guild line:

+  //   * Don't report FV as physical memory

+  //   * MemoryAllocation Hob should only cover physical memory

+  //   * Use ResourceDescriptor Hob to report physical memory or Firmware Device and they shouldn't be overlapped

+  PrintString ("Prepare Cpu HOB information ...\n");

+  PrepareHobCpu ();

+

+  //

+  // 1. BFV

+  //

+  PrintString ("Prepare BFV HOB information ...\n");

+  PrepareHobBfv (Handoff->BfvBase, Handoff->BfvSize);

+

+  //

+  // 2. Updates Memory information, and get the top free address under 4GB

+  //

+  PrintString ("Prepare Memory HOB information ...\n");

+  MemoryTopOnDescriptor = PrepareHobMemory (Handoff->MemDescCount, Handoff->MemDesc);

+  

+  //

+  // 3. Put [NV], [Stack], [PageTable], [MemDesc], [HOB] just below the [top free address under 4GB]

+  //

+  

+  //   3.1 NV data

+  PrintString ("Prepare NV Storage information ...\n");

+  NvStorageBase = PrepareHobNvStorage (MemoryTopOnDescriptor);

+  PrintString ("NV Storage Base = %p\n", NvStorageBase);

+  //   3.2 Stack

+  StackTop = NvStorageBase;

+  StackBottom = PrepareHobStack (StackTop);

+  PrintString ("Stack Top=0x%x, Stack Bottom=0x%x\n", StackTop, StackBottom);

+  //   3.3 Page Table

+  PageTableBase = PreparePageTable (StackBottom, gHob->Cpu.SizeOfMemorySpace);

+  //   3.4 MemDesc (will be used in PlatformBds)

+  MemoryDescriptor = PrepareHobMemoryDescriptor (PageTableBase, Handoff->MemDescCount, Handoff->MemDesc);

+  //   3.5 Copy the Hob itself to EfiMemoryBottom, and update the PHIT Hob

+  PrepareHobPhit (StackTop, MemoryDescriptor);

+

+  //

+  // 4. Register the memory occupied by DxeCore and DxeIpl together as DxeCore

+  //

+  PrintString ("Prepare DxeCore memory Hob ...\n");

+  PrepareHobDxeCore (

+    Handoff->DxeCoreEntryPoint,

+    (EFI_PHYSICAL_ADDRESS)(UINTN)Handoff->DxeCoreImageBase,

+    (UINTN)Handoff->DxeIplImageBase + (UINTN)Handoff->DxeIplImageSize - (UINTN)Handoff->DxeCoreImageBase

+    );

+

+  PrepareHobLegacyTable (gHob);

+  

+  PreparePpisNeededByDxeCore (gHob);

+

+  CompleteHobGeneration ();

+

+  //

+  // Print Hob Info

+  //

+  ClearScreen();

+  PrintString (

+    "HobStart = %p\n"

+    "Memory Top = %lx, Bottom = %lx\n"

+    "Free Memory Top = %lx, Bottom = %lx\n"

+    "NvStorageFvb = %lx, Length = %lx\n"

+    "BfvResource = %lx, Length = %lx\n"

+    "NvStorageFvResource = %lx, Length = %lx\n"

+    "NvStorage = %lx, Length = %lx\n"

+    "NvFtwFvResource = %lx, Length = %lx\n"

+    "NvFtwWorking = %lx, Length = %lx\n"

+    "NvFtwSpare = %lx, Length = %lx\n"

+    "Stack = %lx, StackLength = %lx\n"

+    "PageTable = %p\n"

+    "MemoryFreeUnder1MB = %lx, MemoryFreeUnder1MBLength = %lx\n"

+    "MemoryAbove1MB = %lx, MemoryAbove1MBLength = %lx\n"

+    "MemoryAbove4GB = %lx, MemoryAbove4GBLength = %lx\n"

+    "DxeCore = %lx, DxeCoreLength = %lx\n"

+    "MemoryAllocation = %lx, MemoryLength = %lx\n"

+    "$",

+    gHob,

+    gHob->Phit.EfiMemoryTop, gHob->Phit.EfiMemoryBottom,

+    gHob->Phit.EfiFreeMemoryTop, gHob->Phit.EfiFreeMemoryBottom,

+    gHob->NvStorageFvb.FvbInfo.Entries[0].Base, gHob->NvFtwFvb.FvbInfo.Entries[0].Length,

+    gHob->BfvResource.PhysicalStart, gHob->BfvResource.ResourceLength,

+    gHob->NvStorageFvResource.PhysicalStart, gHob->NvStorageFvResource.ResourceLength,

+    gHob->NvStorage.FvbInfo.Entries[0].Base, gHob->NvStorage.FvbInfo.Entries[0].Length,

+    gHob->NvFtwFvResource.PhysicalStart, gHob->NvFtwFvResource.ResourceLength,

+    gHob->NvFtwWorking.FvbInfo.Entries[0].Base, gHob->NvFtwWorking.FvbInfo.Entries[0].Length,

+    gHob->NvFtwSpare.FvbInfo.Entries[0].Base, gHob->NvFtwSpare.FvbInfo.Entries[0].Length,

+    gHob->Stack.AllocDescriptor.MemoryBaseAddress, gHob->Stack.AllocDescriptor.MemoryLength,

+    PageTableBase,

+    gHob->MemoryFreeUnder1MB.PhysicalStart, gHob->MemoryFreeUnder1MB.ResourceLength,

+    gHob->MemoryAbove1MB.PhysicalStart, gHob->MemoryAbove1MB.ResourceLength,

+    gHob->MemoryAbove4GB.PhysicalStart, gHob->MemoryAbove4GB.ResourceLength,

+    gHob->DxeCore.MemoryAllocationHeader.MemoryBaseAddress, gHob->DxeCore.MemoryAllocationHeader.MemoryLength,

+    gHob->MemoryAllocation.AllocDescriptor.MemoryBaseAddress, gHob->MemoryAllocation.AllocDescriptor.MemoryLength

+    );

+

+  ClearScreen();

+  PrintString (

+    "\n\n\n\n\n\n\n\n\n\n"

+    "                         WELCOME TO EFI WORLD!\n"

+    );

+  

+  EnterDxeMain (StackTop, Handoff->DxeCoreEntryPoint, gHob, PageTableBase);

+  PrintString ("Fail to enter DXE main!\n");

+ 

+  //

+  // Should never get here

+  //

+  CpuDeadLoop ();

+}

+

+EFI_STATUS

+EFIAPI

+_ModuleEntryPoint (

+  IN EFILDRHANDOFF  *Handoff

+  )

+{

+  DxeInit(Handoff);

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.h
new file mode 100644
index 0000000..581c2e6
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.h
@@ -0,0 +1,49 @@
+/** @file

+  Internal header file for DxeIpl module.

+  

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/  

+

+#ifndef _DUET_DXEIPL_H_

+#define _DUET_DXEIPL_H_

+

+#include <FrameworkPei.h>

+

+#include "EfiLdrHandoff.h"

+#include "EfiFlashMap.h"

+

+#include <Guid/MemoryTypeInformation.h>

+#include <Guid/PciExpressBaseAddress.h>

+#include <Guid/AcpiDescription.h>

+

+#include <Guid/MemoryAllocationHob.h>

+#include <Guid/Acpi.h>

+#include <Guid/SmBios.h>

+#include <Guid/Mps.h>

+#include <Guid/FlashMapHob.h>

+#include <Guid/SystemNvDataGuid.h>

+#include <Guid/VariableFormat.h>

+#include <Guid/StatusCodeDataTypeDebug.h>

+#include <Guid/DxeCoreFileName.h>

+#include <Guid/LdrMemoryDescriptor.h>

+

+#include <Protocol/Decompress.h>

+#include <Protocol/StatusCode.h>

+#include <Protocol/FirmwareVolumeBlock.h>

+

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/ReportStatusCodeLib.h>

+#include <Library/PrintLib.h>

+#include <Library/IoLib.h>

+

+#endif // _DUET_DXEIPL_H_

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.inf b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.inf
new file mode 100644
index 0000000..ba7a2c2
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/DxeIpl.inf
@@ -0,0 +1,70 @@
+## @file

+# 

+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#  Module Name:

+#    DxeIpl.inf

+#

+#  Abstract:

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = DxeIpl

+  FILE_GUID                      = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  IntelFrameworkPkg/IntelFrameworkPkg.dec

+

+[LibraryClasses]

+  BaseLib

+  BaseMemoryLib

+  PrintLib

+  SerialPortLib

+  ReportStatusCodeLib

+  IoLib

+

+[Guids]

+  gEfiVariableGuid

+  gDxeCoreFileNameGuid

+  gLdrMemoryDescriptorGuid

+

+[Sources]

+  DxeIpl.h

+  DxeInit.c

+  LegacyTable.c

+  LegacyTable.h

+  PpisNeededByDxeCore.c

+  PpisNeededByDxeCore.h

+  HobGeneration.c

+  HobGeneration.h

+  SerialStatusCode.c

+  SerialStatusCode.h

+  Debug.c

+  Debug.h

+  

+[Sources.x64]

+  X64/EnterDxeCore.c

+  X64/Paging.c

+  X64/VirtualMemory.h

+

+[Sources.Ia32]

+  Ia32/EnterDxeCore.c

+  Ia32/Paging.c

+  Ia32/VirtualMemory.h

+

+[Depex]

+  TRUE

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.c
new file mode 100644
index 0000000..fac74b0
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.c
@@ -0,0 +1,1000 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  HobGeneration.c

+

+Abstract:

+

+Revision History:

+

+**/

+#include "DxeIpl.h"

+#include "HobGeneration.h"

+#include "PpisNeededByDxeCore.h"

+#include "FlashLayout.h"

+#include "Debug.h"

+

+#define EFI_CPUID_EXTENDED_FUNCTION  0x80000000

+#define CPUID_EXTENDED_ADD_SIZE      0x80000008

+#define EBDA_VALUE_ADDRESS           0x40E

+

+HOB_TEMPLATE  gHobTemplate = {

+  { // Phit

+    {  // Header

+      EFI_HOB_TYPE_HANDOFF,                 // HobType

+      sizeof (EFI_HOB_HANDOFF_INFO_TABLE),  // HobLength

+      0                                     // Reserved

+    },

+    EFI_HOB_HANDOFF_TABLE_VERSION,          // Version

+    BOOT_WITH_FULL_CONFIGURATION,           // BootMode

+    0,                                      // EfiMemoryTop

+    0,                                      // EfiMemoryBottom

+    0,                                      // EfiFreeMemoryTop

+    0,                                      // EfiFreeMemoryBottom

+    0                                       // EfiEndOfHobList

+  }, 

+  { // Bfv

+    {

+      EFI_HOB_TYPE_FV,                      // HobType

+      sizeof (EFI_HOB_FIRMWARE_VOLUME),     // HobLength

+      0                                     // Reserved

+    },

+    0,                                      // BaseAddress

+    0                                       // Length

+  },

+  { // BfvResource

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,     // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength

+      0                                     // Reserved

+    },

+    {

+      0                                     // Owner Guid

+    },

+    EFI_RESOURCE_FIRMWARE_DEVICE,           // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |

+     EFI_RESOURCE_ATTRIBUTE_TESTED |

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),  // ResourceAttribute

+    0,                                              // PhysicalStart

+    0                                               // ResourceLength

+  },

+  { // Cpu

+    { // Header

+      EFI_HOB_TYPE_CPU,                     // HobType

+      sizeof (EFI_HOB_CPU),                 // HobLength

+      0                                     // Reserved

+    },

+    52,                                     // SizeOfMemorySpace - Architecture Max

+    16,                                     // SizeOfIoSpace,

+    {

+      0, 0, 0, 0, 0, 0                      // Reserved[6]

+    }

+  },

+  {   // Stack HOB

+    {   // header

+      EFI_HOB_TYPE_MEMORY_ALLOCATION,               // Hob type

+      sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK),     // Hob size

+      0                                             // reserved

+    },

+    {

+      EFI_HOB_MEMORY_ALLOC_STACK_GUID,

+      0x0,                                          // EFI_PHYSICAL_ADDRESS  MemoryBaseAddress;

+      0x0,                                          // UINT64                MemoryLength;

+      EfiBootServicesData,                          // EFI_MEMORY_TYPE       MemoryType;  

+      {0, 0, 0, 0}                                  // Reserved              Reserved[4]; 

+    }

+  },

+  { // MemoryAllocation for HOB's & Images

+    {

+      EFI_HOB_TYPE_MEMORY_ALLOCATION,               // HobType

+      sizeof (EFI_HOB_MEMORY_ALLOCATION),           // HobLength

+      0                                             // Reserved

+    },

+    {

+      {

+        0, //EFI_HOB_MEMORY_ALLOC_MODULE_GUID       // Name

+      },

+      0x0,                                          // EFI_PHYSICAL_ADDRESS  MemoryBaseAddress;

+      0x0,                                          // UINT64                MemoryLength;

+      EfiBootServicesData,                          // EFI_MEMORY_TYPE       MemoryType;  

+      {

+        0, 0, 0, 0                                  // Reserved              Reserved[4]; 

+      }

+    }

+   },

+  { // MemoryFreeUnder1MB for unused memory that DXE core will claim

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,             // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR),         // HobLength

+      0                                             // Reserved

+    },

+    {

+      0                                             // Owner Guid

+    },

+    EFI_RESOURCE_SYSTEM_MEMORY,                     // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT                 |

+     EFI_RESOURCE_ATTRIBUTE_TESTED                  |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED             |

+     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE             | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE       | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),     

+    0x0,                                            // PhysicalStart

+    0                                               // ResourceLength

+  },

+  { // MemoryFreeAbove1MB for unused memory that DXE core will claim

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,             // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR),         // HobLength

+      0                                             // Reserved

+    },

+    {

+      0                                             // Owner Guid

+    },

+    EFI_RESOURCE_SYSTEM_MEMORY,                     // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT                 |

+     EFI_RESOURCE_ATTRIBUTE_TESTED                  |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED             |

+     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE             | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE       | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),     

+    0x0,                                            // PhysicalStart

+    0                                               // ResourceLength

+  },

+  { // MemoryFreeAbove4GB for unused memory that DXE core will claim

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,             // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR),         // HobLength

+      0                                             // Reserved

+    },

+    {

+      0                                             // Owner Guid

+    },

+    EFI_RESOURCE_SYSTEM_MEMORY,                     // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT                 |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED             |

+     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE             | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE       | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),     

+    0x0,                                            // PhysicalStart

+    0                                               // ResourceLength

+  },

+  {   // Memory Allocation Module for DxeCore

+    {   // header

+      EFI_HOB_TYPE_MEMORY_ALLOCATION,               // Hob type

+      sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE),    // Hob size

+      0                                             // reserved

+    },

+    {

+      EFI_HOB_MEMORY_ALLOC_MODULE_GUID,

+      0x0,                                          // EFI_PHYSICAL_ADDRESS  MemoryBaseAddress;

+      0x0,                                          // UINT64                MemoryLength;

+      EfiBootServicesCode,                          // EFI_MEMORY_TYPE       MemoryType;  

+      {

+        0, 0, 0, 0                                  // UINT8                 Reserved[4]; 

+      },

+    },

+    DXE_CORE_FILE_NAME_GUID,

+    0x0                                             //  EFI_PHYSICAL_ADDRESS of EntryPoint;

+  },

+  { // MemoryDxeCore

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,             // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR),         // HobLength

+      0                                             // Reserved

+    },

+    {

+      0                                             // Owner Guid

+    },

+    EFI_RESOURCE_SYSTEM_MEMORY,                     // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT                 |

+//     EFI_RESOURCE_ATTRIBUTE_TESTED                  | // Do not mark as TESTED, or DxeCore will find it and use it before check Allocation

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED             |

+     EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE             | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE       | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),     

+    0x0,                                            // PhysicalStart

+    0                                               // ResourceLength

+  },

+  { // Memory Map Hints to reduce fragmentation in the memory map

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,                    // Hob type

+        sizeof (MEMORY_TYPE_INFORMATION_HOB),           // Hob size

+        0,                                              // reserved

+      },

+      EFI_MEMORY_TYPE_INFORMATION_GUID

+    },

+    {

+      {

+        EfiACPIReclaimMemory,

+        0x80

+      },  // 0x80 pages = 512k for ASL

+      {

+        EfiACPIMemoryNVS,

+        0x100

+      },  // 0x100 pages = 1024k for S3, SMM, etc

+      {

+        EfiReservedMemoryType,

+        0x04

+      },  // 16k for BIOS Reserved

+      {

+        EfiRuntimeServicesData,

+        0x100

+      },

+      {

+        EfiRuntimeServicesCode,

+        0x100

+      },

+      {

+        EfiBootServicesCode,

+        0x200

+      },

+      {

+        EfiBootServicesData,

+        0x200

+      },

+      {

+        EfiLoaderCode,

+        0x100

+      },

+      {

+        EfiLoaderData,

+        0x100

+      },

+      {

+        EfiMaxMemoryType,

+        0

+      }

+    }

+  },

+  { // Pointer to ACPI Table

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (TABLE_HOB),                // Hob size

+        0                                  // reserved

+      },

+      EFI_ACPI_TABLE_GUID

+    },

+    0

+  },

+  { // Pointer to ACPI20 Table

+    {

+      {  

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (TABLE_HOB),                // Hob size

+        0                                  // reserved

+      },

+      EFI_ACPI_20_TABLE_GUID

+    },

+    0

+  },

+  { // Pointer to SMBIOS Table

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (TABLE_HOB),                // Hob size

+        0                                  // reserved

+      },

+      SMBIOS_TABLE_GUID

+    },

+    0

+  },

+  { // Pointer to MPS Table

+    {

+      {

+         EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (TABLE_HOB),                // Hob size

+        0,                                 // reserved

+      },

+      EFI_MPS_TABLE_GUID

+    },

+    0

+  },

+  /**

+  { // Pointer to FlushInstructionCache

+    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+    sizeof (PROTOCOL_HOB),             // Hob size

+    0,                                 // reserved

+    EFI_PEI_FLUSH_INSTRUCTION_CACHE_GUID,

+    NULL

+  },

+  { // Pointer to TransferControl

+    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+    sizeof (PROTOCOL_HOB),             // Hob size

+    0,                                 // reserved

+    EFI_PEI_TRANSFER_CONTROL_GUID,

+    NULL

+  },

+  { // Pointer to PeCoffLoader

+    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+    sizeof (PROTOCOL_HOB),             // Hob size

+    0,                                 // reserved

+    EFI_PEI_PE_COFF_LOADER_GUID,

+    NULL

+  },

+  { // Pointer to EfiDecompress

+    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+    sizeof (PROTOCOL_HOB),             // Hob size

+    0,                                 // reserved

+    EFI_DECOMPRESS_PROTOCOL_GUID,

+    NULL

+  },

+  { // Pointer to TianoDecompress

+    EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+    sizeof (PROTOCOL_HOB),             // Hob size

+    0,                                 // reserved

+    EFI_TIANO_DECOMPRESS_PROTOCOL_GUID,

+    NULL

+  },

+  **/

+  { // Pointer to ReportStatusCode

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (PROTOCOL_HOB),             // Hob size

+        0                                  // reserved

+      },

+      EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID

+    },

+    0

+  },

+  { // EFILDR Memory Descriptor

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (MEMORY_DESC_HOB),          // Hob size

+        0                                  // reserved

+      },

+      LDR_MEMORY_DESCRIPTOR_GUID

+    },

+    0,

+    NULL

+  },

+  { // Pci Express Base Address Hob

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (PCI_EXPRESS_BASE_HOB),     // Hob size

+        0                                  // reserved

+      },

+      EFI_PCI_EXPRESS_BASE_ADDRESS_GUID

+    },

+    {

+      0,

+      0,

+      0,

+    }

+  },

+  { // Acpi Description Hob

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (ACPI_DESCRIPTION_HOB),     // Hob size

+        0                                  // reserved

+      },

+      EFI_ACPI_DESCRIPTION_GUID

+    },

+    {

+      {

+        0,

+      },

+    }

+  },

+  { // NV Storage FV Resource

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,     // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength

+      0                                     // Reserved

+    },

+    {

+      0                                     // Owner Guid

+    },

+    EFI_RESOURCE_FIRMWARE_DEVICE,           // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |

+     EFI_RESOURCE_ATTRIBUTE_TESTED |

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),  // ResourceAttribute

+    0,                                              // PhysicalStart (Fixed later)

+    NV_STORAGE_FVB_SIZE                             // ResourceLength

+  },

+  { // FVB holding NV Storage

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (FVB_HOB),

+        0

+      },

+      EFI_FLASH_MAP_HOB_GUID

+    },

+    {

+      {0, 0, 0},                       // Reserved[3]

+      EFI_FLASH_AREA_GUID_DEFINED,     // AreaType

+      EFI_SYSTEM_NV_DATA_FV_GUID ,     // AreaTypeGuid

+      1,

+      {

+        {

+          EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes

+          0,                             // SubAreaData.Reserved

+          0,                             // SubAreaData.Base (Fixed later)

+          NV_STORAGE_FVB_SIZE,           // SubAreaData.Length

+          EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem

+        }

+      }, 

+      0,                               // VolumeSignature (Fixed later)

+      NV_STORAGE_FILE_PATH,            // Mapped file without padding

+                                       //  TotalFVBSize = FileSize + PaddingSize = multiple of BLOCK_SIZE

+      NV_STORAGE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH,

+                                       // ActuralSize

+      EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH

+    }

+  },

+  { // NV Storage Hob

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (FVB_HOB),                  // Hob size

+        0                                  // reserved

+      },

+      EFI_FLASH_MAP_HOB_GUID

+    },

+    {

+      {0, 0, 0},                       // Reserved[3]

+      EFI_FLASH_AREA_EFI_VARIABLES,    // AreaType

+      { 0 },                           // AreaTypeGuid

+      1,

+      {

+        {

+          EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes

+          0,                             // SubAreaData.Reserved

+          0,                             // SubAreaData.Base (Fixed later)

+          NV_STORAGE_SIZE,               // SubAreaData.Length

+          EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem

+        }

+      }, 

+      0,

+      NV_STORAGE_FILE_PATH,

+      NV_STORAGE_SIZE,

+      0

+    }

+  },

+  { // NV Ftw FV Resource

+    {

+      EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,     // HobType

+      sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), // HobLength

+      0                                     // Reserved

+    },

+    {

+      0                                     // Owner Guid

+    },

+    EFI_RESOURCE_FIRMWARE_DEVICE,           // ResourceType

+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |

+     EFI_RESOURCE_ATTRIBUTE_INITIALIZED |

+     EFI_RESOURCE_ATTRIBUTE_TESTED |

+     EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE),  // ResourceAttribute

+    0,                                              // PhysicalStart (Fixed later)

+    NV_FTW_FVB_SIZE                                 // ResourceLength

+  },  

+  { // FVB holding FTW spaces including Working & Spare space

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (FVB_HOB),

+        0

+      },

+      EFI_FLASH_MAP_HOB_GUID

+    },

+    {

+      {0, 0, 0},                       // Reserved[3]

+      EFI_FLASH_AREA_GUID_DEFINED,     // AreaType

+      EFI_SYSTEM_NV_DATA_FV_GUID,      // AreaTypeGuid

+      1,

+      {

+        {

+          EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes

+          0,                             // SubAreaData.Reserved

+          0,                             // SubAreaData.Base (Fixed later)

+          NV_FTW_FVB_SIZE,               // SubAreaData.Length

+          EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID   // SubAreaData.FileSystem

+        }

+      }, 

+      0,

+      L"",                             // Empty String indicates using memory

+      0,

+      0

+    }

+  },

+  { // NV Ftw working Hob

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (FVB_HOB),                  // Hob size

+        0                                  // reserved

+      },

+      EFI_FLASH_MAP_HOB_GUID

+    },

+    {

+      {0, 0, 0},                       // Reserved[3]

+      EFI_FLASH_AREA_FTW_STATE,        // AreaType

+      { 0 },                           // AreaTypeGuid

+      1,

+      {

+        {

+          EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes

+          0,                             // SubAreaData.Reserved

+          0,                             // SubAreaData.Base (Fixed later)

+          NV_FTW_WORKING_SIZE,           // SubAreaData.Length

+          EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem

+        }

+      }, 

+      0,                               // VolumeSignature

+      L"",

+      0,

+      0

+    }

+  },

+  { // NV Ftw spare Hob

+    {

+      {

+        EFI_HOB_TYPE_GUID_EXTENSION,       // Hob type

+        sizeof (FVB_HOB),                  // Hob size

+        0                                  // reserved

+      },

+      EFI_FLASH_MAP_HOB_GUID

+    },

+    {

+      {0, 0, 0},                       // Reserved[3]

+      EFI_FLASH_AREA_FTW_BACKUP,       // AreaType

+      { 0 },                           // AreaTypeGuid

+      1,

+      {

+        {

+          EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, // SubAreaData.Attributes

+          0,                             // SubAreaData.Reserved

+          0,                             // SubAreaData.Base (Fixed later)

+          NV_FTW_SPARE_SIZE,             // SubAreaData.Length

+          EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID // SubAreaData.FileSystem

+        }

+      }, 

+      0,

+      L"",

+      0,

+      0

+    }

+  },

+  { // EndOfHobList

+    EFI_HOB_TYPE_END_OF_HOB_LIST,      // HobType

+    sizeof (EFI_HOB_GENERIC_HEADER),   // HobLength

+    0                                  // Reserved

+  }

+};

+

+HOB_TEMPLATE  *gHob = &gHobTemplate;

+

+VOID *

+PrepareHobMemory (

+  IN UINTN                    NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  )

+/*++

+Description:

+  Update the Hob filling MemoryFreeUnder1MB, MemoryAbove1MB, MemoryAbove4GB

+

+Arguments:

+  NumberOfMemoryMapEntries - Count of Memory Descriptors

+  EfiMemoryDescriptor      - Point to the buffer containing NumberOfMemoryMapEntries Memory Descriptors

+

+Return:

+  VOID * : The end address of MemoryAbove1MB (or the top free memory under 4GB)

+--*/

+{

+  UINTN                Index;

+  UINT64               EbdaAddress;

+

+  //

+  // Prepare Low Memory

+  // 0x18 pages is 72 KB.

+  //

+  EbdaAddress = ((UINT64)(*(UINT16 *)(UINTN)(EBDA_VALUE_ADDRESS))) << 4;

+  if (EbdaAddress < 0x9A000 || EbdaAddress > EFI_MEMORY_BELOW_1MB_END) {

+    //

+    // EBDA should not go below 0x9A000 in any implementation,

+    // so add check here to make sure EBDA_VALUE_ADDRESS has a valid value.

+    //

+    EbdaAddress = EFI_MEMORY_BELOW_1MB_END;

+  }

+  gHob->MemoryFreeUnder1MB.ResourceLength = EbdaAddress - EFI_MEMORY_BELOW_1MB_START;

+  gHob->MemoryFreeUnder1MB.PhysicalStart  = EFI_MEMORY_BELOW_1MB_START;

+

+  //

+  // Prepare High Memory

+  // Assume Memory Map is ordered from low to high

+  //

+  gHob->MemoryAbove1MB.PhysicalStart   = 0;

+  gHob->MemoryAbove1MB.ResourceLength  = 0;

+  gHob->MemoryAbove4GB.PhysicalStart   = 0;

+  gHob->MemoryAbove4GB.ResourceLength  = 0;

+

+  for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {

+    //

+    // Skip regions below 1MB

+    //

+    if (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000) {

+      continue;

+    }

+    //

+    // Process regions above 1MB

+    //

+    if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000) {

+      if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) {

+        if (gHob->MemoryAbove1MB.PhysicalStart == 0) {

+          gHob->MemoryAbove1MB.PhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart;

+          gHob->MemoryAbove1MB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);

+        } else if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength == EfiMemoryDescriptor[Index].PhysicalStart) {

+          gHob->MemoryAbove1MB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);

+        }

+      }

+      if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) ||

+          (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) {

+        continue;

+      }

+      if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) ||

+          (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) {

+        break;

+      }

+    }

+    //

+    // Process region above 4GB

+    //

+    if (EfiMemoryDescriptor[Index].PhysicalStart >= 0x100000000LL) {

+      if (EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) {

+        if (gHob->MemoryAbove4GB.PhysicalStart == 0) {

+          gHob->MemoryAbove4GB.PhysicalStart  = EfiMemoryDescriptor[Index].PhysicalStart;

+          gHob->MemoryAbove4GB.ResourceLength = LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);

+        }

+        if (gHob->MemoryAbove4GB.PhysicalStart + gHob->MemoryAbove4GB.ResourceLength == 

+            EfiMemoryDescriptor[Index].PhysicalStart) {

+          gHob->MemoryAbove4GB.ResourceLength += LShiftU64 (EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT);

+        }

+      }

+    }

+  }

+

+  if (gHob->MemoryAbove4GB.ResourceLength == 0) {

+    //

+    // If there is no memory above 4GB then change the resource descriptor HOB

+    //  into another type. I'm doing this as it's unclear if a resource

+    //  descriptor HOB of length zero is valid. Spec does not say it's illegal,

+    //  but code in EDK does not seem to handle this case.

+    //

+    gHob->MemoryAbove4GB.Header.HobType = EFI_HOB_TYPE_UNUSED;

+  }

+

+  return (VOID *)(UINTN)(gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength);

+}

+

+VOID *

+PrepareHobStack (

+  IN VOID *StackTop

+  )

+{

+  gHob->Stack.AllocDescriptor.MemoryLength      = EFI_MEMORY_STACK_PAGE_NUM * EFI_PAGE_SIZE;

+  gHob->Stack.AllocDescriptor.MemoryBaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)StackTop - gHob->Stack.AllocDescriptor.MemoryLength;

+

+  return (VOID *)(UINTN)gHob->Stack.AllocDescriptor.MemoryBaseAddress;

+}

+

+VOID *

+PrepareHobMemoryDescriptor (

+  VOID                          *MemoryDescriptorTop,

+  UINTN                         MemDescCount,

+  EFI_MEMORY_DESCRIPTOR         *MemDesc

+  )

+{

+  gHob->MemoryDescriptor.MemDescCount = MemDescCount;

+  gHob->MemoryDescriptor.MemDesc      = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryDescriptorTop - MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR));

+  //

+  // Make MemoryDescriptor.MemDesc page aligned

+  //

+  gHob->MemoryDescriptor.MemDesc      = (EFI_MEMORY_DESCRIPTOR *)((UINTN) gHob->MemoryDescriptor.MemDesc & ~EFI_PAGE_MASK);

+

+  CopyMem (gHob->MemoryDescriptor.MemDesc, MemDesc, MemDescCount * sizeof(EFI_MEMORY_DESCRIPTOR));

+

+  return gHob->MemoryDescriptor.MemDesc;

+}

+

+VOID

+PrepareHobBfv (

+  VOID  *Bfv,

+  UINTN BfvLength

+  )

+{

+  //UINTN BfvLengthPageSize;

+

+  //

+  // Calculate BFV location at top of the memory region.

+  // This is like a RAM Disk. Align to page boundry.

+  //

+  //BfvLengthPageSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (BfvLength));

+ 

+  gHob->Bfv.BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Bfv;

+  gHob->Bfv.Length = BfvLength;

+

+  //

+  // Resource descriptor for the FV

+  //

+  gHob->BfvResource.PhysicalStart = gHob->Bfv.BaseAddress;

+  gHob->BfvResource.ResourceLength = gHob->Bfv.Length;

+}

+

+VOID

+PrepareHobDxeCore (

+  VOID                  *DxeCoreEntryPoint,

+  EFI_PHYSICAL_ADDRESS  DxeCoreImageBase,

+  UINT64                DxeCoreLength

+  )

+{

+  gHob->DxeCore.MemoryAllocationHeader.MemoryBaseAddress = DxeCoreImageBase;

+  gHob->DxeCore.MemoryAllocationHeader.MemoryLength = DxeCoreLength;

+  gHob->DxeCore.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)DxeCoreEntryPoint;

+

+

+  gHob->MemoryDxeCore.PhysicalStart   = DxeCoreImageBase;

+  gHob->MemoryDxeCore.ResourceLength  = DxeCoreLength;  

+}

+

+VOID *

+PrepareHobNvStorage (

+  VOID *NvStorageTop

+  )

+/*

+  Initialize Block-Aligned Firmware Block.

+

+  Variable:

+           +-------------------+

+           |     FV_Header     |

+           +-------------------+

+           |                   |

+           |VAR_STORAGE(0x4000)|

+           |                   |

+           +-------------------+

+  FTW:

+           +-------------------+

+           |     FV_Header     |

+           +-------------------+

+           |                   |

+           |   Working(0x2000) |

+           |                   |

+           +-------------------+

+           |                   |

+           |   Spare(0x10000)  |

+           |                   |

+           +-------------------+

+*/

+{

+  STATIC VARIABLE_STORE_HEADER VarStoreHeader = {

+    VARIABLE_STORE_SIGNATURE,

+    0xffffffff,                 // will be fixed in Variable driver

+    VARIABLE_STORE_FORMATTED,

+    VARIABLE_STORE_HEALTHY,

+    0,

+    0

+  };

+  

+  STATIC EFI_FIRMWARE_VOLUME_HEADER NvStorageFvbHeader = {

+    {

+      0,

+    },  // ZeroVector[16]

+    EFI_SYSTEM_NV_DATA_FV_GUID,

+    NV_STORAGE_FVB_SIZE,

+    EFI_FVH_SIGNATURE,

+    EFI_FVB_READ_ENABLED_CAP |

+      EFI_FVB_READ_STATUS |

+      EFI_FVB_WRITE_ENABLED_CAP |

+      EFI_FVB_WRITE_STATUS |

+      EFI_FVB_ERASE_POLARITY,

+    EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH,

+    0,  // CheckSum

+    0,  // ExtHeaderOffset

+    {

+      0,

+    },  // Reserved[1]

+    1,  // Revision

+    {

+      {

+        NV_STORAGE_FVB_BLOCK_NUM,

+        FV_BLOCK_SIZE,

+      }

+    }

+  };

+

+  STATIC EFI_FV_BLOCK_MAP_ENTRY BlockMapEntryEnd = {0, 0};

+

+  EFI_PHYSICAL_ADDRESS StorageFvbBase;

+  EFI_PHYSICAL_ADDRESS FtwFvbBase;

+

+  UINT16               *Ptr;

+  UINT16               Checksum;

+

+

+  //

+  // Use first 16-byte Reset Vector of FVB to store extra information

+  //   UINT32 Offset 0 stores the volume signature

+  //   UINT8  Offset 4 : should init the Variable Store Header if non-zero

+  //

+  gHob->NvStorageFvb.FvbInfo.VolumeId   = *(UINT32 *) (UINTN) (NV_STORAGE_STATE);

+  gHob->NvStorage.   FvbInfo.VolumeId   = *(UINT32 *) (UINTN) (NV_STORAGE_STATE);

+

+  //

+  // *(NV_STORAGE_STATE + 4):

+  //   2 - Size error

+  //   1 - File not exist

+  //   0 - File exist with correct size

+  //

+  if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) == 2) {

+    ClearScreen ();

+    PrintString ("Error: Size of Efivar.bin should be 16k!\n");

+    CpuDeadLoop();

+  }

+  

+  if (*(UINT8 *) (UINTN) (NV_STORAGE_STATE + 4) != 0) {

+    //

+    // Efivar.bin doesn't exist

+    //  1. Init variable storage header to valid header

+    //

+    CopyMem (

+      (VOID *) (UINTN) NV_STORAGE_START,

+      &VarStoreHeader,

+      sizeof (VARIABLE_STORE_HEADER)

+    );

+    //

+    //  2. set all bits in variable storage body to 1

+    //

+    SetMem (

+      (VOID *) (UINTN) (NV_STORAGE_START + sizeof (VARIABLE_STORE_HEADER)),

+      NV_STORAGE_SIZE - sizeof (VARIABLE_STORE_HEADER),

+      0xff

+    );

+  }

+

+  //

+  // Relocate variable storage

+  // 

+  //  1. Init FVB Header to valid header: First 0x48 bytes

+  //     In real platform, these fields are fixed by tools

+  //

+  //

+  Checksum = 0;

+  for (

+    Ptr = (UINT16 *) &NvStorageFvbHeader; 

+    Ptr < (UINT16 *) ((UINTN) (UINT8 *) &NvStorageFvbHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER));

+    ++Ptr

+    ) {

+    Checksum = (UINT16) (Checksum + (*Ptr));

+  }

+  NvStorageFvbHeader.Checksum = (UINT16) (0x10000 - Checksum);

+  StorageFvbBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)NvStorageTop - NV_STORAGE_FVB_SIZE - NV_FTW_FVB_SIZE) & ~EFI_PAGE_MASK);

+  CopyMem ((VOID *) (UINTN) StorageFvbBase, &NvStorageFvbHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER));

+  CopyMem (

+    (VOID *) (UINTN) (StorageFvbBase + sizeof (EFI_FIRMWARE_VOLUME_HEADER)),

+    &BlockMapEntryEnd,

+    sizeof (EFI_FV_BLOCK_MAP_ENTRY)

+  );

+  

+  //

+  //  2. Relocate variable data

+  //

+  CopyMem (

+    (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH),

+    (VOID *) (UINTN) NV_STORAGE_START,

+    NV_STORAGE_SIZE

+  );

+

+  //

+  //  3. Set the remaining memory to 0xff

+  //

+  SetMem (

+    (VOID *) (UINTN) (StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_STORAGE_SIZE),

+    NV_STORAGE_FVB_SIZE - NV_STORAGE_SIZE - EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH,

+    0xff

+  );

+

+  //

+  // Create the FVB holding NV Storage in memory

+  //

+  gHob->NvStorageFvResource.PhysicalStart =

+    gHob->NvStorageFvb.FvbInfo.Entries[0].Base = StorageFvbBase;

+  //

+  // Create the NV Storage Hob

+  //

+  gHob->NvStorage.FvbInfo.Entries[0].Base = StorageFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH;

+

+  //

+  // Create the FVB holding FTW spaces

+  //

+  FtwFvbBase = (EFI_PHYSICAL_ADDRESS)((UINTN) StorageFvbBase + NV_STORAGE_FVB_SIZE);

+  gHob->NvFtwFvResource.PhysicalStart =

+    gHob->NvFtwFvb.FvbInfo.Entries[0].Base = FtwFvbBase;

+  //

+  // Put FTW Working in front

+  //

+  gHob->NvFtwWorking.FvbInfo.Entries[0].Base = FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH;

+

+  //

+  // Put FTW Spare area after FTW Working area

+  //

+  gHob->NvFtwSpare.FvbInfo.Entries[0].Base = 

+    (EFI_PHYSICAL_ADDRESS)((UINTN) FtwFvbBase + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + NV_FTW_WORKING_SIZE);

+  

+  return (VOID *)(UINTN)StorageFvbBase;

+}

+

+VOID

+PrepareHobPhit (

+  VOID *MemoryTop,

+  VOID *FreeMemoryTop

+  )

+{

+  gHob->Phit.EfiMemoryTop        = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryTop;

+  gHob->Phit.EfiMemoryBottom     = gHob->Phit.EfiMemoryTop - CONSUMED_MEMORY;

+  gHob->Phit.EfiFreeMemoryTop    = (EFI_PHYSICAL_ADDRESS)(UINTN)FreeMemoryTop;

+  gHob->Phit.EfiFreeMemoryBottom = gHob->Phit.EfiMemoryBottom + sizeof(HOB_TEMPLATE);

+

+  CopyMem ((VOID *)(UINTN)gHob->Phit.EfiMemoryBottom, gHob, sizeof(HOB_TEMPLATE));

+  gHob = (HOB_TEMPLATE *)(UINTN)gHob->Phit.EfiMemoryBottom;

+

+  gHob->Phit.EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)&gHob->EndOfHobList;

+}

+

+VOID

+PrepareHobCpu (

+  VOID

+  )

+{

+  UINT32  CpuidEax;

+

+  //

+  // Create a CPU hand-off information

+  //

+  gHob->Cpu.SizeOfMemorySpace = 36;

+

+  AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &CpuidEax, NULL, NULL, NULL);

+  if (CpuidEax >= CPUID_EXTENDED_ADD_SIZE) {

+    AsmCpuid (CPUID_EXTENDED_ADD_SIZE, &CpuidEax, NULL, NULL, NULL);

+    gHob->Cpu.SizeOfMemorySpace = (UINT8)(CpuidEax & 0xFF);

+  }

+}

+

+VOID

+CompleteHobGeneration (

+  VOID

+  )

+{

+  gHob->MemoryAllocation.AllocDescriptor.MemoryBaseAddress  = gHob->Phit.EfiFreeMemoryTop;

+  //

+  // Reserve all the memory under Stack above FreeMemoryTop as allocated

+  //

+  gHob->MemoryAllocation.AllocDescriptor.MemoryLength       = gHob->Stack.AllocDescriptor.MemoryBaseAddress - gHob->Phit.EfiFreeMemoryTop;

+

+  //

+  // adjust Above1MB ResourceLength

+  //

+  if (gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength > gHob->Phit.EfiMemoryTop) {

+    gHob->MemoryAbove1MB.ResourceLength = gHob->Phit.EfiMemoryTop - gHob->MemoryAbove1MB.PhysicalStart;

+  }

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.h
new file mode 100644
index 0000000..f9f8f31
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/HobGeneration.h
@@ -0,0 +1,171 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  HobGeneration.h

+

+Abstract:

+

+Revision History:

+

+**/

+

+#ifndef _DXELDR_HOB_GENERATION_H_

+#define _DXELDR_HOB_GENERATION_H_

+

+#include "DxeIpl.h"

+

+#define EFI_MEMORY_BELOW_1MB_START     0x86000

+#define EFI_MEMORY_BELOW_1MB_END       0x9F800

+#define EFI_MEMORY_STACK_PAGE_NUM      0x20

+#define CONSUMED_MEMORY                0x100000 * 80

+

+#define NV_STORAGE_START               0x15000

+#define NV_STORAGE_STATE               0x19000

+

+#pragma pack(1)

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  EFI_MEMORY_TYPE_INFORMATION   Info[10];

+} MEMORY_TYPE_INFORMATION_HOB;

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  EFI_PHYSICAL_ADDRESS          Table;

+} TABLE_HOB;

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  EFI_PHYSICAL_ADDRESS          Interface;

+} PROTOCOL_HOB;

+

+typedef struct {

+  EFI_HOB_GUID_TYPE                         Hob;

+  // Note: we get only one PCI Segment now.

+  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION  PciExpressBaseAddressInfo;

+} PCI_EXPRESS_BASE_HOB;

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  EFI_ACPI_DESCRIPTION          AcpiDescription;

+} ACPI_DESCRIPTION_HOB;

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  EFI_FLASH_MAP_FS_ENTRY_DATA   FvbInfo;

+} FVB_HOB;

+

+typedef struct {

+  EFI_HOB_HANDOFF_INFO_TABLE        Phit;

+  EFI_HOB_FIRMWARE_VOLUME           Bfv;

+  EFI_HOB_RESOURCE_DESCRIPTOR       BfvResource;

+  EFI_HOB_CPU                       Cpu;

+  EFI_HOB_MEMORY_ALLOCATION_STACK   Stack;

+  EFI_HOB_MEMORY_ALLOCATION         MemoryAllocation;

+  EFI_HOB_RESOURCE_DESCRIPTOR       MemoryFreeUnder1MB;

+  EFI_HOB_RESOURCE_DESCRIPTOR       MemoryAbove1MB;

+  EFI_HOB_RESOURCE_DESCRIPTOR       MemoryAbove4GB;

+  EFI_HOB_MEMORY_ALLOCATION_MODULE  DxeCore;

+  EFI_HOB_RESOURCE_DESCRIPTOR       MemoryDxeCore;

+  MEMORY_TYPE_INFORMATION_HOB       MemoryTypeInfo;

+  TABLE_HOB                         Acpi;

+  TABLE_HOB                         Acpi20;

+  TABLE_HOB                         Smbios;

+  TABLE_HOB                         Mps;

+  /**

+  PROTOCOL_HOB                      FlushInstructionCache;

+  PROTOCOL_HOB                      TransferControl;

+  PROTOCOL_HOB                      PeCoffLoader;

+  PROTOCOL_HOB                      EfiDecompress;

+  PROTOCOL_HOB                      TianoDecompress;

+  **/

+  PROTOCOL_HOB                      SerialStatusCode;

+  MEMORY_DESC_HOB                   MemoryDescriptor;

+  PCI_EXPRESS_BASE_HOB              PciExpress;

+  ACPI_DESCRIPTION_HOB              AcpiInfo;

+  

+  EFI_HOB_RESOURCE_DESCRIPTOR       NvStorageFvResource;

+

+  FVB_HOB                           NvStorageFvb;

+  FVB_HOB                           NvStorage;

+  

+  EFI_HOB_RESOURCE_DESCRIPTOR       NvFtwFvResource;

+  FVB_HOB                           NvFtwFvb;

+  FVB_HOB                           NvFtwWorking;

+  FVB_HOB                           NvFtwSpare;

+  

+  EFI_HOB_GENERIC_HEADER            EndOfHobList;

+} HOB_TEMPLATE;

+

+#pragma pack()

+

+extern HOB_TEMPLATE  *gHob;

+

+VOID *

+PrepareHobStack (

+  IN VOID *StackTop

+  );

+

+VOID

+PrepareHobBfv (

+  VOID  *Bfv,

+  UINTN BfvLength

+  );

+

+VOID *

+PrepareHobMemory (

+  IN UINTN                    NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  );

+

+VOID

+PrepareHobDxeCore (

+  VOID                  *DxeCoreEntryPoint,

+  EFI_PHYSICAL_ADDRESS  DxeCoreImageBase,

+  UINT64                DxeCoreLength

+  );

+

+VOID *

+PreparePageTable (

+  VOID  *PageNumberTop,

+  UINT8 SizeOfMemorySpace

+  );

+

+VOID *

+PrepareHobMemoryDescriptor (

+  VOID                          *MemoryDescriptorTop,

+  UINTN                         MemDescCount,

+  EFI_MEMORY_DESCRIPTOR         *MemDesc

+  );

+

+VOID

+PrepareHobPhit (

+  VOID *MemoryTop,

+  VOID *FreeMemoryTop

+  );

+

+VOID *

+PrepareHobNvStorage (

+  VOID *NvStorageTop

+  );

+

+VOID

+PrepareHobCpu (

+  VOID

+  );

+

+VOID

+CompleteHobGeneration (

+  VOID

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/EnterDxeCore.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/EnterDxeCore.c
new file mode 100644
index 0000000..aff0ac6
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/EnterDxeCore.c
@@ -0,0 +1,31 @@
+/** @file

+  IA32 specific code to enter DxeCore

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#include "DxeIpl.h"

+

+VOID

+EnterDxeMain (

+  IN VOID *StackTop,

+  IN VOID *DxeCoreEntryPoint,

+  IN VOID *Hob,

+  IN VOID *PageTable

+  )

+{

+  SwitchStack (

+    (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,

+    Hob,

+    NULL,

+    StackTop

+    );

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/Paging.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/Paging.c
new file mode 100644
index 0000000..eb44042
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/Paging.c
@@ -0,0 +1,172 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Paging.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include "DxeIpl.h"

+#include "HobGeneration.h"

+#include "VirtualMemory.h"

+#include "Debug.h"

+

+#define EFI_PAGE_SIZE_4K      0x1000

+#define EFI_PAGE_SIZE_4M      0x400000

+

+//

+// Create 4G 4M-page table

+// PDE (31:22)   :  1024 entries

+//

+#define EFI_MAX_ENTRY_NUM     1024

+

+#define EFI_PDE_ENTRY_NUM     EFI_MAX_ENTRY_NUM

+

+#define EFI_PDE_PAGE_NUM      1

+

+#define EFI_PAGE_NUMBER_4M    (EFI_PDE_PAGE_NUM)

+

+//

+// Create 4M 4K-page table

+// PTE (21:12)   :  1024 entries

+//

+#define EFI_PTE_ENTRY_NUM     EFI_MAX_ENTRY_NUM

+#define EFI_PTE_PAGE_NUM      1

+

+#define EFI_PAGE_NUMBER_4K    (EFI_PTE_PAGE_NUM)

+

+#define EFI_PAGE_NUMBER       (EFI_PAGE_NUMBER_4M + EFI_PAGE_NUMBER_4K)

+

+VOID

+EnableNullPointerProtection (

+  UINT8 *PageTable

+  )

+{

+  IA32_PAGE_TABLE_ENTRY_4K                      *PageTableEntry4KB;

+

+  PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K);

+

+  //

+  // Fill in the Page Table entries

+  // Mark 0~4K as not present

+  //

+  PageTableEntry4KB->Bits.Present = 0;

+

+  return ;

+}

+

+VOID

+Ia32Create4KPageTables (

+  UINT8 *PageTable

+  )

+{

+  UINT64                                        PageAddress;

+  UINTN                                         PTEIndex;

+  IA32_PAGE_DIRECTORY_ENTRY_4K                  *PageDirectoryEntry4KB;

+  IA32_PAGE_TABLE_ENTRY_4K                      *PageTableEntry4KB;

+

+  PageAddress = 0;

+

+  //

+  //  Page Table structure 2 level 4K.

+  //

+  //  Page Table 4K  : PageDirectoryEntry4K      : bits 31-22

+  //                   PageTableEntry            : bits 21-12

+  //

+

+  PageTableEntry4KB = (IA32_PAGE_TABLE_ENTRY_4K *)((UINTN)PageTable + EFI_PAGE_NUMBER_4M * EFI_PAGE_SIZE_4K);

+  PageDirectoryEntry4KB = (IA32_PAGE_DIRECTORY_ENTRY_4K *)((UINTN)PageTable);

+

+  PageDirectoryEntry4KB->Uint32 = (UINT32)(UINTN)PageTableEntry4KB;

+  PageDirectoryEntry4KB->Bits.ReadWrite = 0;

+  PageDirectoryEntry4KB->Bits.Present = 1;

+  PageDirectoryEntry4KB->Bits.MustBeZero = 1;

+

+  for (PTEIndex = 0; PTEIndex < EFI_PTE_ENTRY_NUM; PTEIndex++, PageTableEntry4KB++) {

+    //

+    // Fill in the Page Table entries

+    //

+    PageTableEntry4KB->Uint32 = (UINT32)PageAddress;

+    PageTableEntry4KB->Bits.ReadWrite = 1;

+    PageTableEntry4KB->Bits.Present = 1;

+

+    PageAddress += EFI_PAGE_SIZE_4K;

+  }

+

+  return ;

+}

+

+VOID

+Ia32Create4MPageTables (

+  UINT8 *PageTable

+  )

+{

+  UINT32                                        PageAddress;

+  UINT8                                         *TempPageTable;

+  UINTN                                         PDEIndex;

+  IA32_PAGE_TABLE_ENTRY_4M                      *PageDirectoryEntry4MB;

+

+  TempPageTable = PageTable;

+

+  PageAddress = 0;

+

+  //

+  //  Page Table structure 1 level 4MB.

+  //

+  //  Page Table 4MB : PageDirectoryEntry4M      : bits 31-22

+  //

+

+  PageDirectoryEntry4MB = (IA32_PAGE_TABLE_ENTRY_4M *)TempPageTable;

+

+  for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry4MB++) {

+    //

+    // Fill in the Page Directory entries

+    //

+    PageDirectoryEntry4MB->Uint32 = (UINT32)PageAddress;

+    PageDirectoryEntry4MB->Bits.ReadWrite = 1;

+    PageDirectoryEntry4MB->Bits.Present = 1;

+    PageDirectoryEntry4MB->Bits.MustBe1 = 1;

+

+    PageAddress += EFI_PAGE_SIZE_4M;

+  }

+

+  return ;

+}

+

+VOID *

+PreparePageTable (

+  VOID  *PageNumberTop,

+  UINT8 SizeOfMemorySpace 

+  )

+/*++

+Description:

+  Generate pagetable below PageNumberTop, 

+  and return the bottom address of pagetable for putting other things later.

+--*/

+{

+  VOID *PageNumberBase;

+

+  PageNumberBase = (VOID *)((UINTN)PageNumberTop - EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K);

+  ZeroMem (PageNumberBase, EFI_PAGE_NUMBER * EFI_PAGE_SIZE_4K);

+

+  Ia32Create4MPageTables (PageNumberBase);

+  Ia32Create4KPageTables (PageNumberBase);

+  //

+  // Not enable NULL Pointer Protection if using INTX call

+  //

+//  EnableNullPointerProtection (PageNumberBase);

+

+  return PageNumberBase;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/VirtualMemory.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/VirtualMemory.h
new file mode 100644
index 0000000..0b5fc0e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/Ia32/VirtualMemory.h
@@ -0,0 +1,88 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  VirtualMemory.h

+

+Abstract:

+

+Revision History:

+

+**/

+  

+#ifndef _VIRTUAL_MEMORY_H_

+#define _VIRTUAL_MEMORY_H_

+

+#pragma pack(1)

+

+//

+// Page Directory Entry 4K

+//

+typedef union {

+  struct {

+    UINT32  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT32  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT32  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT32  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT32  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT32  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT32  MustBeZero:3;             // Must Be Zero

+    UINT32  Available:3;              // Available for use by system software

+    UINT32  PageTableBaseAddress:20;  // Page Table Base Address

+  } Bits;

+  UINT32    Uint32;

+} IA32_PAGE_DIRECTORY_ENTRY_4K;

+

+//

+// Page Table Entry 4K

+//

+typedef union {

+  struct {

+    UINT32  Present:1;                // 0 = Not present in memory, 1 = Present in memory 

+    UINT32  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT32  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT32  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT32  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT32  Accessed:1;               // 0 = Not accessed (cleared by software), 1 = Accessed (set by CPU)

+    UINT32  Dirty:1;                  // 0 = Not written to (cleared by software), 1 = Written to (set by CPU)

+    UINT32  PAT:1;                    // 0 = Disable PAT, 1 = Enable PAT

+    UINT32  Global:1;                 // Ignored

+    UINT32  Available:3;              // Available for use by system software

+    UINT32  PageTableBaseAddress:20;  // Page Table Base Address

+  } Bits;

+  UINT32    Uint32;

+} IA32_PAGE_TABLE_ENTRY_4K;

+

+//

+// Page Table Entry 4M

+//

+typedef union {

+  struct {

+    UINT32  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT32  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT32  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT32  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT32  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT32  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT32  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page

+    UINT32  MustBe1:1;                // Must be 1 

+    UINT32  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write

+    UINT32  Available:3;              // Available for use by system software

+    UINT32  PAT:1;                    //

+    UINT32  MustBeZero:9;             // Must be zero;

+    UINT32  PageTableBaseAddress:10;  // Page Table Base Address

+  } Bits;

+  UINT32    Uint32;

+} IA32_PAGE_TABLE_ENTRY_4M;

+

+#pragma pack()

+

+#endif 

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.c
new file mode 100644
index 0000000..1c822f8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.c
@@ -0,0 +1,357 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  LegacyTable.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include "DxeIpl.h"

+#include "HobGeneration.h"

+#include "Debug.h"

+

+#define MPS_PTR           SIGNATURE_32('_','M','P','_')

+#define SMBIOS_PTR        SIGNATURE_32('_','S','M','_')

+

+#define EBDA_BASE_ADDRESS 0x40E

+

+VOID *

+FindAcpiRsdPtr (

+  VOID

+  )

+{

+  UINTN                           Address;

+  UINTN                           Index;

+

+  //

+  // First Seach 0x0e0000 - 0x0fffff for RSD Ptr

+  //

+  for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {

+    if (*(UINT64 *)(Address) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {

+      return (VOID *)Address;

+    }

+  }

+

+  //

+  // Search EBDA

+  //

+

+  Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4;

+  for (Index = 0; Index < 0x400 ; Index += 16) {

+    if (*(UINT64 *)(Address + Index) == EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE) {

+      return (VOID *)Address;

+    }

+  }

+  return NULL;

+}

+

+VOID *

+FindSMBIOSPtr (

+  VOID

+  )

+{

+  UINTN                           Address;

+

+  //

+  // First Seach 0x0f0000 - 0x0fffff for SMBIOS Ptr

+  //

+  for (Address = 0xf0000; Address < 0xfffff; Address += 0x10) {

+    if (*(UINT32 *)(Address) == SMBIOS_PTR) {

+      return (VOID *)Address;

+    }

+  }

+  return NULL;

+}

+

+VOID *

+FindMPSPtr (

+  VOID

+  )

+{

+  UINTN                           Address;

+  UINTN                           Index;

+

+  //

+  // First Seach 0x0e0000 - 0x0fffff for MPS Ptr

+  //

+  for (Address = 0xe0000; Address < 0xfffff; Address += 0x10) {

+    if (*(UINT32 *)(Address) == MPS_PTR) {

+      return (VOID *)Address;

+    }

+  }

+

+  //

+  // Search EBDA

+  //

+

+  Address = (*(UINT16 *)(UINTN)(EBDA_BASE_ADDRESS)) << 4;

+  for (Index = 0; Index < 0x400 ; Index += 16) {

+    if (*(UINT32 *)(Address + Index) == MPS_PTR) {

+      return (VOID *)Address;

+    }

+  }

+  return NULL;

+}

+

+#pragma pack(1)

+

+typedef struct {

+  EFI_ACPI_DESCRIPTION_HEADER  Header;

+  UINT32                       Entry;

+} RSDT_TABLE;

+

+typedef struct {

+  EFI_ACPI_DESCRIPTION_HEADER  Header;

+  UINT64                       Entry;

+} XSDT_TABLE;

+

+#pragma pack()

+

+VOID

+ScanTableInRSDT (

+  RSDT_TABLE                   *Rsdt,

+  UINT32                       Signature,

+  EFI_ACPI_DESCRIPTION_HEADER  **FoundTable

+  )

+{

+  UINTN                         Index;

+  UINT32                        EntryCount;

+  UINT32                        *EntryPtr;

+  EFI_ACPI_DESCRIPTION_HEADER   *Table;

+  

+  *FoundTable = NULL;

+  

+  EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);

+  

+  EntryPtr = &Rsdt->Entry;

+  for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {

+    Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));

+    if (Table->Signature == Signature) {

+      *FoundTable = Table;

+      break;

+    }

+  }

+  

+  return;

+}

+

+VOID

+ScanTableInXSDT (

+  XSDT_TABLE                   *Xsdt,

+  UINT32                       Signature,

+  EFI_ACPI_DESCRIPTION_HEADER  **FoundTable

+  )

+{

+  UINTN                        Index;

+  UINT32                       EntryCount;

+  UINT64                       EntryPtr;

+  UINTN                        BasePtr;

+  EFI_ACPI_DESCRIPTION_HEADER  *Table;

+  

+  *FoundTable = NULL;

+  

+  EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);

+  

+  BasePtr = (UINTN)(&(Xsdt->Entry));

+  for (Index = 0; Index < EntryCount; Index ++) {

+    CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));

+    Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));

+    if (Table->Signature == Signature) {

+      *FoundTable = Table;

+      break;

+    }

+  }

+  

+  return;

+}

+

+VOID *

+FindAcpiPtr (

+  IN HOB_TEMPLATE  *Hob,

+  UINT32           Signature

+  )

+{

+  EFI_ACPI_DESCRIPTION_HEADER                    *AcpiTable;

+  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *Rsdp;

+  RSDT_TABLE                                     *Rsdt;

+  XSDT_TABLE                                     *Xsdt;

+ 

+  AcpiTable = NULL;

+

+  //

+  // Check ACPI2.0 table

+  //

+  if ((int)Hob->Acpi20.Table != -1) {

+    Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi20.Table;

+    Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;

+    Xsdt = NULL;

+    if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {

+      Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;

+    }

+    //

+    // Check Xsdt

+    //

+    if (Xsdt != NULL) {

+      ScanTableInXSDT (Xsdt, Signature, &AcpiTable);

+    }

+    //

+    // Check Rsdt

+    //

+    if ((AcpiTable == NULL) && (Rsdt != NULL)) {

+      ScanTableInRSDT (Rsdt, Signature, &AcpiTable);

+    }

+  }

+  

+  //

+  // Check ACPI1.0 table

+  //

+  if ((AcpiTable == NULL) && ((int)Hob->Acpi.Table != -1)) {

+    Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)Hob->Acpi.Table;

+    Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;

+    //

+    // Check Rsdt

+    //

+    if (Rsdt != NULL) {

+      ScanTableInRSDT (Rsdt, Signature, &AcpiTable);

+    }

+  }

+

+  return AcpiTable;

+}

+

+#pragma pack(1)

+typedef struct {

+  UINT64  BaseAddress;

+  UINT16  PciSegmentGroupNumber;

+  UINT8   StartBusNumber;

+  UINT8   EndBusNumber;

+  UINT32  Reserved;

+} MCFG_STRUCTURE;

+#pragma pack()

+

+VOID

+PrepareMcfgTable (

+  IN HOB_TEMPLATE  *Hob

+  )

+{

+  EFI_ACPI_DESCRIPTION_HEADER  *McfgTable;

+  MCFG_STRUCTURE               *Mcfg;

+  UINTN                        McfgCount;

+  UINTN                        Index;

+

+  McfgTable = FindAcpiPtr (Hob, EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE);

+  if (McfgTable == NULL) {

+    return ;

+  }

+

+  Mcfg = (MCFG_STRUCTURE *)((UINTN)McfgTable + sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64));

+  McfgCount = (McfgTable->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER) - sizeof(UINT64)) / sizeof(MCFG_STRUCTURE);

+

+  //

+  // Fill PciExpress info on Hob

+  // Note: Only for 1st segment

+  //

+  for (Index = 0; Index < McfgCount; Index++) {

+    if (Mcfg[Index].PciSegmentGroupNumber == 0) {

+      Hob->PciExpress.PciExpressBaseAddressInfo.PciExpressBaseAddress = Mcfg[Index].BaseAddress;

+      break;

+    }

+  }

+

+  return ;

+}

+

+VOID

+PrepareFadtTable (

+  IN HOB_TEMPLATE  *Hob

+  )

+{

+  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE   *Fadt;

+  EFI_ACPI_DESCRIPTION                        *AcpiDescription;

+

+  Fadt = FindAcpiPtr (Hob, EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);

+  if (Fadt == NULL) {

+    return ;

+  }

+

+  AcpiDescription = &Hob->AcpiInfo.AcpiDescription;

+  //

+  // Fill AcpiDescription according to FADT

+  // Currently, only for PM_TMR

+  //

+  AcpiDescription->PM_TMR_LEN = Fadt->PmTmrLen;

+  AcpiDescription->TMR_VAL_EXT = (UINT8)((Fadt->Flags & 0x100) != 0);

+ 

+  //

+  // For fields not included in ACPI 1.0 spec, we get the value based on table length

+  //

+  if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, XPmTmrBlk) + sizeof (Fadt->XPmTmrBlk)) {

+    CopyMem (

+      &AcpiDescription->PM_TMR_BLK,

+      &Fadt->XPmTmrBlk,

+      sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE)

+      );

+  }

+  if (Fadt->Header.Length >= OFFSET_OF (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE, ResetValue) + sizeof (Fadt->ResetValue)) {

+    CopyMem (

+      &AcpiDescription->RESET_REG,

+      &Fadt->ResetReg,

+      sizeof(EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE)

+      );

+    AcpiDescription->RESET_VALUE = Fadt->ResetValue;

+  }

+

+  if (AcpiDescription->PM_TMR_BLK.Address == 0) {

+    AcpiDescription->PM_TMR_BLK.Address          = Fadt->PmTmrBlk;

+    AcpiDescription->PM_TMR_BLK.AddressSpaceId   = EFI_ACPI_3_0_SYSTEM_IO;

+  }

+

+  //

+  // It's possible that the PM_TMR_BLK.RegisterBitWidth is always 32,

+  //  we need to set the correct RegisterBitWidth value according to the TMR_VAL_EXT

+  //  A zero indicates TMR_VAL is implemented as a 24-bit value. 

+  //  A one indicates TMR_VAL is implemented as a 32-bit value

+  //

+  AcpiDescription->PM_TMR_BLK.RegisterBitWidth = (UINT8) ((AcpiDescription->TMR_VAL_EXT == 0) ? 24 : 32);

+  

+

+  return ;

+}

+

+VOID

+PrepareHobLegacyTable (

+  IN HOB_TEMPLATE  *Hob

+  )

+{

+  CHAR8    PrintBuffer[256];

+

+  Hob->Acpi.Table   = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr ();

+  AsciiSPrint (PrintBuffer, 256, "\nAcpiTable=0x%x ", (UINT32)(UINTN)Hob->Acpi.Table);

+  PrintString (PrintBuffer);

+  Hob->Acpi20.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindAcpiRsdPtr ();

+  Hob->Smbios.Table = (EFI_PHYSICAL_ADDRESS)(UINTN)FindSMBIOSPtr ();

+  AsciiSPrint (PrintBuffer, 256, "SMBIOS Table=0x%x ", (UINT32)(UINTN)Hob->Smbios.Table);

+  PrintString (PrintBuffer);

+  Hob->Mps.Table    = (EFI_PHYSICAL_ADDRESS)(UINTN)FindMPSPtr ();

+  AsciiSPrint (PrintBuffer, 256, "MPS Table=0x%x\n", (UINT32)(UINTN)Hob->Mps.Table);

+  PrintString (PrintBuffer);

+

+  PrepareMcfgTable (Hob);

+

+  PrepareFadtTable (Hob);

+

+  return ;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.h
new file mode 100644
index 0000000..755ce25
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/LegacyTable.h
@@ -0,0 +1,31 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  LegacyTable.h

+

+Abstract:

+

+Revision History:

+

+**/

+

+#ifndef _DXELDR_LEGACY_TABLE_H_

+#define _DXELDR_LEGACY_TABLE_H_

+

+#include "HobGeneration.h"

+

+VOID

+PrepareHobLegacyTable (

+  IN HOB_TEMPLATE  *Hob

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.c
new file mode 100644
index 0000000..e08a148
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.c
@@ -0,0 +1,59 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PpisNeededByDxeCore.c

+

+Abstract:

+  

+Revision History:

+

+**/

+

+#include "PpisNeededByDxeCore.h"

+#include "HobGeneration.h"

+#include "SerialStatusCode.h"

+

+EFI_STATUS

+EFIAPI

+PreparePpisNeededByDxeCore (

+  IN HOB_TEMPLATE  *Hob

+  )

+/*++

+

+Routine Description:

+

+  This routine adds the PPI/Protocol Hobs that are consumed by the DXE Core.

+  Normally these come from PEI, but since our PEI was 32-bit we need an

+  alternate source. That is this driver.

+

+  This driver does not consume PEI or DXE services and thus updates the 

+  Phit (HOB list) directly

+

+Arguments:

+

+  HobStart - Pointer to the beginning of the HOB List from PEI

+

+Returns:

+

+  This function should after it has add it's HOBs

+

+--*/

+{

+  EFI_REPORT_STATUS_CODE                    ReportStatusCode;

+

+  InstallSerialStatusCode (&ReportStatusCode);

+  Hob->SerialStatusCode.Interface = (EFI_PHYSICAL_ADDRESS) (UINTN) ReportStatusCode;

+

+  return EFI_SUCCESS;

+}

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.h
new file mode 100644
index 0000000..c7bd013
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/PpisNeededByDxeCore.h
@@ -0,0 +1,64 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PpisNeededByDxeCore.h

+

+Abstract:

+  

+Revision History:

+

+**/

+

+#ifndef _DXELDR_PPIS_NEEDED_BY_DXE_CORE_H_

+#define _DXELDR_PPIS_NEEDED_BY_DXE_CORE_H_

+

+#include "DxeIpl.h"

+#include "HobGeneration.h"

+

+//EFI_STATUS

+//InstallEfiPeiTransferControl (

+//  IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This

+//  );

+

+//EFI_STATUS

+//InstallEfiPeiFlushInstructionCache (

+//  IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL  **This

+//  );

+

+EFI_STATUS

+EFIAPI

+PreparePpisNeededByDxeCore (

+  IN  HOB_TEMPLATE  *HobStart

+  )

+/*++

+

+Routine Description:

+

+  This routine adds the PPI/Protocol Hobs that are consumed by the DXE Core.

+  Normally these come from PEI, but since our PEI was 32-bit we need an

+  alternate source. That is this driver.

+

+  This driver does not consume PEI or DXE services and thus updates the 

+  Phit (HOB list) directly

+

+Arguments:

+

+  HobStart - Pointer to the beginning of the HOB List from PEI

+

+Returns:

+

+  This function should after it has add it's HOBs

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.c
new file mode 100644
index 0000000..1595932
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.c
@@ -0,0 +1,760 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  SerialStatusCode.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include <Library/SerialPortLib.h>

+#include "SerialStatusCode.h"

+

+//

+// All of the lookup tables are only needed in debug.

+//

+

+typedef struct {

+  UINT32                  Value;

+  CHAR8                   *Token;

+} STATUS_CODE_LOOKUP_TABLE;

+

+STATUS_CODE_LOOKUP_TABLE mSeverityToken[] = {

+  { EFI_ERROR_MINOR,                "ERROR_MINOR" },

+  { EFI_ERROR_MAJOR,                "ERROR_MAJOR" },

+  { EFI_ERROR_UNRECOVERED,          "ERROR_UNRECOVERED" },

+  { EFI_ERROR_UNCONTAINED,          "ERROR_UNCONTAINED" },

+  { 0xFFFFFFFF,                     "ERROR_UNRECOGNIZED"  }

+  };

+

+STATUS_CODE_LOOKUP_TABLE mClassSubClassToken[] = {

+  { EFI_COMPUTING_UNIT_UNSPECIFIED,             "COMPUTING_UNIT_UNSPECIFIED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR,          "COMPUTING_UNIT_HOST_PROCESSOR" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR,          "COMPUTING_UNIT_FIRMWARE_PROCESSOR" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR,            "COMPUTING_UNIT_IO_PROCESSOR" },

+  { EFI_COMPUTING_UNIT_CACHE,                   "COMPUTING_UNIT_CACHE" },

+  { EFI_COMPUTING_UNIT_MEMORY,            "COMPUTING_UNIT_MEMORY" },

+  { EFI_COMPUTING_UNIT_CHIPSET,           "COMPUTING_UNIT_CHIPSET" },

+  { EFI_PERIPHERAL_UNSPECIFIED,           "PERIPHERAL_UNSPECIFIED" },

+  { EFI_PERIPHERAL_KEYBOARD,              "PERIPHERAL_KEYBOARD" },

+  { EFI_PERIPHERAL_MOUSE,                 "PERIPHERAL_MOUSE" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE,          "PERIPHERAL_LOCAL_CONSOLE" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE,          "PERIPHERAL_REMOTE_CONSOLE" },

+  { EFI_PERIPHERAL_SERIAL_PORT,          "PERIPHERAL_SERIAL_PORT" },

+  { EFI_PERIPHERAL_PARALLEL_PORT,          "PERIPHERAL_PARALLEL_PORT" },

+  { EFI_PERIPHERAL_FIXED_MEDIA,          "PERIPHERAL_FIXED_MEDIA" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA,          "PERIPHERAL_REMOVABLE_MEDIA" },

+  { EFI_PERIPHERAL_AUDIO_INPUT,          "PERIPHERAL_AUDIO_INPUT" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT,          "PERIPHERAL_AUDIO_OUTPUT" },

+  { EFI_PERIPHERAL_LCD_DEVICE,          "PERIPHERAL_LCD_DEVICE" },

+  { EFI_IO_BUS_UNSPECIFIED,          "IO_BUS_UNSPECIFIED" },

+  { EFI_IO_BUS_PCI,          "IO_BUS_PCI" },

+  { EFI_IO_BUS_USB,          "IO_BUS_USB" },

+  { EFI_IO_BUS_IBA,          "IO_BUS_IBA" },

+  { EFI_IO_BUS_AGP,          "IO_BUS_AGP" },

+  { EFI_IO_BUS_PC_CARD,          "IO_BUS_PC_CARD" },

+  { EFI_IO_BUS_LPC,          "IO_BUS_LPC" },

+  { EFI_IO_BUS_SCSI,          "IO_BUS_SCSI" },

+  { EFI_IO_BUS_ATA_ATAPI,          "IO_BUS_ATA_ATAPI" },

+  { EFI_IO_BUS_FC,          "IO_BUS_FC" },

+  { EFI_IO_BUS_IP_NETWORK,          "IO_BUS_IP_NETWORK" },

+  { EFI_IO_BUS_SMBUS,          "IO_BUS_SMBUS" },

+  { EFI_IO_BUS_I2C,          "IO_BUS_I2C" },

+  { EFI_SOFTWARE_UNSPECIFIED,          "SOFTWARE_UNSPECIFIED" },

+  { EFI_SOFTWARE_SEC,          "SOFTWARE_SEC" },

+  { EFI_SOFTWARE_PEI_CORE,          "SOFTWARE_PEI_CORE" },

+  { EFI_SOFTWARE_PEI_MODULE,          "SOFTWARE_PEI_MODULE" },

+  { EFI_SOFTWARE_DXE_CORE,          "SOFTWARE_DXE_CORE" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE,          "SOFTWARE_EFI_BOOT_SERVICE" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE,          "SOFTWARE_EFI_RUNTIME_SERVICE" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER,          "SOFTWARE_DXE_BS_DRIVER" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER,          "SOFTWARE_DXE_RT_DRIVER" },

+  { EFI_SOFTWARE_SMM_DRIVER,         "SOFTWARE_SMM_DRIVER" },

+  { EFI_SOFTWARE_RT,          "SOFTWARE_EFI_RT" },

+  { EFI_SOFTWARE_AL,          "SOFTWARE_EFI_AL" },

+  { EFI_SOFTWARE_EFI_APPLICATION,          "SOFTWARE_EFI_APPLICATION" },

+  { EFI_SOFTWARE_EFI_OS_LOADER,          "SOFTWARE_EFI_OS_LOADER" },

+  { 0xFFFFFFFF,          "ERROR_UNRECOGNIZED"  }

+  };

+

+STATUS_CODE_LOOKUP_TABLE mOperationToken[] = {

+  { EFI_COMPUTING_UNIT_UNSPECIFIED          | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_UNSPECIFIED          | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_UNSPECIFIED          | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_UNSPECIFIED          | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_UNSPECIFIED          | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_INVALID_TYPE,          "INVALID_TYPE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_INVALID_SPEED,          "INVALID_SPEED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_MISMATCH,          "MISMATCH" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_TIMER_EXPIRED,          "TIMER_EXPIRED" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_SELF_TEST,          "SELF_TEST" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_INTERNAL,          "INTERNAL" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_THERMAL,          "THERMAL" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_LOW_VOLTAGE,          "LOW_VOLTAGE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_HIGH_VOLTAGE,          "HIGH_VOLTAGE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_CACHE,          "CACHE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_MICROCODE_UPDATE,          "MICROCODE_UPDATE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_NO_MICROCODE_UPDATE,          "NO_MICROCODE_UPDATE" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_CORRECTABLE,         "1XECC" },

+  { EFI_COMPUTING_UNIT_HOST_PROCESSOR       | EFI_CU_HP_EC_UNCORRECTABLE,          "2XECC" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR   | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR   | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR   | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR   | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR   | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR         | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR         | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR         | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR         | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_IO_PROCESSOR         | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_CACHE_EC_INVALID_TYPE,          "INVALID_TYPE" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_CACHE_EC_INVALID_SPEED,          "INVALID_SPEED" },

+  { EFI_COMPUTING_UNIT_CACHE                | EFI_CU_CACHE_EC_INVALID_SIZE,          "INVALID_SIZE" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_INVALID_TYPE,          "INVALID_TYPE" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_INVALID_SPEED,          "INVALID_SPEED" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_CORRECTABLE,          "1XECC" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_UNCORRECTABLE,        "2XECC" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_SPD_FAIL,          "SPD_FAIL" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_INVALID_SIZE,          "INVALID_SIZE" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_MISMATCH,          "MISMATCH" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_S3_RESUME_FAIL,          "S3_RESUME_FAIL" },

+  { EFI_COMPUTING_UNIT_MEMORY               | EFI_CU_MEMORY_EC_UPDATE_FAIL,          "UPDATE_FAIL" },

+  { EFI_COMPUTING_UNIT_CHIPSET              | EFI_CU_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_COMPUTING_UNIT_CHIPSET              | EFI_CU_EC_DISABLED,          "DISABLED" },

+  { EFI_COMPUTING_UNIT_CHIPSET              | EFI_CU_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_COMPUTING_UNIT_CHIPSET              | EFI_CU_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_COMPUTING_UNIT_CHIPSET              | EFI_CU_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_UNSPECIFIED              | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_KEYBOARD_EC_LOCKED,          "LOCKED" },

+  { EFI_PERIPHERAL_KEYBOARD                 | EFI_P_KEYBOARD_EC_STUCK_KEY,          "STUCK_KEY" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_MOUSE                    | EFI_P_MOUSE_EC_LOCKED,          "LOCKED" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_LOCAL_CONSOLE            | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_REMOTE_CONSOLE           | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_SERIAL_PORT              | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_PARALLEL_PORT            | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_FIXED_MEDIA              | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_REMOVABLE_MEDIA          | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_INPUT              | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_AUDIO_OUTPUT             | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_DISABLED,          "DISABLED" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_INPUT_ERROR,          "INPUT_ERROR" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_OUTPUT_ERROR,          "OUTPUT_ERROR" },

+  { EFI_PERIPHERAL_LCD_DEVICE               | EFI_P_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_UNSPECIFIED                  | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_PCI_EC_PERR,          "PERR" },

+  { EFI_IO_BUS_PCI                          | EFI_IOB_PCI_EC_SERR,          "SERR" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_USB                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_IBA                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_AGP                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_PC_CARD                      | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_LPC                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_SCSI                         | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_ATA_ATAPI                    | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_FC                           | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_IP_NETWORK                   | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_SMBUS                        | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_DISABLED,          "DISABLED" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_NOT_SUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_NOT_DETECTED,          "NOT_DETECTED" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_NOT_CONFIGURED,          "NOT_CONFIGURED" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_INTERFACE_ERROR,          "INTERFACE_ERROR" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_CONTROLLER_ERROR,          "CONTROLLER_ERROR" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_READ_ERROR,          "READ_ERROR" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_WRITE_ERROR,          "WRITE_ERROR" },

+  { EFI_IO_BUS_I2C                          | EFI_IOB_EC_RESOURCE_CONFLICT,          "RESOURCE_CONFLICT" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_UNSPECIFIED                | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_SEC                    | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_PEI_CORE               | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_PEI_MODULE             | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_DXE_CORE               | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_EFI_BOOT_SERVICE           | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_EFI_RUNTIME_SERVICE        | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_DXE_BS_DRIVER          | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_DXE_RT_DRIVER          | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_SMM_DRIVER                    | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_RT                     | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_AL                     | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_EFI_APPLICATION        | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_NON_SPECIFIC,          "NON_SPECIFIC" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_LOAD_ERROR,          "LOAD_ERROR" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_INVALID_PARAMETER,          "INVALID_PARAMETER" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_UNSUPPORTED,          "NOT_SUPPORTED" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_INVALID_BUFFER,          "INVALID_BUFFER" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_OUT_OF_RESOURCES,          "OUT_OF_RESOURCES" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_ABORTED,          "ABORTED" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE,          "ILLEGAL_SOFTWARE_STATE" },

+  { EFI_SOFTWARE_EFI_OS_LOADER              | EFI_SW_EC_ILLEGAL_HARDWARE_STATE,          "ILLEGAL_HARDWARE_STATE" },

+  { 0xFFFFFFFF,                              "ERROR_UNRECOGNIZED"                }

+  };

+

+

+EFI_STATUS

+MatchString (

+  IN  STATUS_CODE_LOOKUP_TABLE  *Table,

+  IN  UINT32                    Value,

+  OUT CHAR8                     **Token

+  );

+

+//

+// Function implemenations

+//

+

+//

+// Match is only needed for debug.

+//

+

+EFI_STATUS

+MatchString (

+  IN  STATUS_CODE_LOOKUP_TABLE  *Table,

+  IN  UINT32                    Value,

+  OUT CHAR8                     **Token

+  )

+/*++

+

+Routine Description: 

+

+  Search the input table for a matching value and return the token associated

+  with that value.  Well formed tables will have the last value == 0 and will 

+  return a default token.

+

+Arguments:  

+

+  Table     Pointer to first entry in an array of table entries.

+  Value     Value to look up.

+  Token     String to return.

+

+Returns:  

+

+  EFI_SUCCESS   The function always returns success.

+

+--*/

+{

+  UINTN         Current;

+  

+  Current = 0;

+  *Token = 0;

+

+  while (!*Token) {

+    //

+    // Found token if values match or current entry is the last entry.

+    //

+    if ((Table[Current].Value == (-1)) ||

+        (Table[Current].Value == Value)) {

+      *Token = Table[Current].Token;

+    }

+    Current++;

+  }

+  return EFI_SUCCESS;

+}

+

+

+EFI_STATUS

+EFIAPI 

+SerialReportStatusCode (

+  IN EFI_STATUS_CODE_TYPE     CodeType,

+  IN EFI_STATUS_CODE_VALUE    Value,

+  IN UINT32                   Instance,

+  IN EFI_GUID                 *CallerId,

+  IN EFI_STATUS_CODE_DATA     *Data OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  Provide a serial port print

+

+Arguments:

+

+  PeiServices - General purpose services available to every PEIM.

+    

+Returns:

+

+  Status -  EFI_SUCCESS if the interface could be successfully

+            installed

+

+--*/

+{

+  CHAR8                   Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];

+  UINT32                  LineNumber;

+  CHAR8                   *Filename;

+  CHAR8                   *Description;

+  CHAR8                   *Format;

+  BASE_LIST               Marker;

+  UINT32                  ErrorLevel;

+  UINTN                   CharCount = 0;

+

+  Buffer[0] = '\0';

+

+  if (Data != NULL && 

+      ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {

+    //

+    // Processes PEI_ASSERT ()

+    //

+    CharCount = AsciiSPrint (

+      Buffer,

+      sizeof (Buffer),

+      "\nPEI_ASSERT!: %a (%d): %a\n",

+      Filename,

+      LineNumber,

+      Description

+      );

+

+  } else if (Data != NULL &&

+             ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {

+    //

+    // Process PEI_DEBUG () macro to Serial

+    //

+    CharCount = AsciiBSPrint (Buffer, sizeof (Buffer), Format, Marker);

+

+  } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { 

+    //

+    // Process Errors

+    //

+    CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "ERROR: C%x:V%x I%x", CodeType, Value, Instance);

+    //

+    // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.

+    //

+    if (CallerId) {

+      CharCount += AsciiSPrint (&Buffer[CharCount - 1], (sizeof (Buffer) - (sizeof(Buffer[0]) * CharCount)), " %g", CallerId);

+    }

+    if (Data) {

+      CharCount += AsciiSPrint (&Buffer[CharCount - 1], (sizeof (Buffer) - (sizeof(Buffer[0]) * CharCount)), " %x", Data);

+    }

+    CharCount += AsciiSPrint (&Buffer[CharCount - 1], (sizeof (Buffer) - (sizeof(Buffer[0]) * CharCount)), "\n");

+

+  }

+

+  if (Buffer[0] != '\0') {

+    //

+    // Callout to platform Lib function to do print.

+    //

+    SerialPortWrite ((UINT8 *) Buffer, CharCount);

+  }

+

+  //

+  // Debug code to display human readable code information.

+  //

+    {

+      CHAR8       *SeverityToken;

+      CHAR8       *SubClassToken;

+      CHAR8       *OperationToken;

+

+      if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { 

+        //

+        // Get the severity token

+        //

+        MatchString (

+          mSeverityToken,

+          (CodeType & EFI_STATUS_CODE_SEVERITY_MASK),

+          &SeverityToken

+          );

+    

+        //

+        // Get the Class/SubClass token

+        //

+        MatchString (

+          mClassSubClassToken,

+          (Value & (EFI_STATUS_CODE_CLASS_MASK | EFI_STATUS_CODE_SUBCLASS_MASK)),

+          &SubClassToken

+          );

+    

+        //

+        // Get the operation token

+        //

+        MatchString (

+          mOperationToken,

+          (Value & (EFI_STATUS_CODE_CLASS_MASK | EFI_STATUS_CODE_SUBCLASS_MASK | EFI_STATUS_CODE_OPERATION_MASK)),

+          &OperationToken

+          );

+    

+        //

+        // Concatenate the instance

+        //

+        CharCount = AsciiSPrint (

+          Buffer,

+          sizeof (Buffer),

+          "%a:%a:%a:%d\n",

+          SeverityToken,

+          SubClassToken,

+          OperationToken,

+          Instance

+          );

+

+        SerialPortWrite ((UINT8 *) Buffer, CharCount);

+      }

+    }

+

+  return EFI_SUCCESS;

+}

+

+

+VOID

+InstallSerialStatusCode (

+  IN EFI_REPORT_STATUS_CODE    *ReportStatusCode

+  )

+/*++

+

+Routine Description:

+

+  Initialize Serial Port and Status Code Handler

+

+Arguments: 

+

+  ReportStatusCode - A pointer to the handler

+

+Returns: 

+

+  None

+

+--*/

+{

+  SerialPortInitialize();

+  *ReportStatusCode = SerialReportStatusCode;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.h
new file mode 100644
index 0000000..7146927
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/SerialStatusCode.h
@@ -0,0 +1,39 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  SerialStatusCode.h

+

+Abstract:

+

+Revision History:

+

+**/

+

+#ifndef _DXELDR_SERIAL_STATUS_CODE_H_

+#define _DXELDR_SERIAL_STATUS_CODE_H_

+

+//

+// Statements that include other files

+//

+#include "DxeIpl.h"

+

+//

+// GUID consumed

+//

+

+

+VOID

+InstallSerialStatusCode (

+  IN EFI_REPORT_STATUS_CODE    *ReportStatusCode

+  );

+

+#endif 

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/EnterDxeCore.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/EnterDxeCore.c
new file mode 100644
index 0000000..10376b5
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/EnterDxeCore.c
@@ -0,0 +1,32 @@
+/** @file

+  x64 specific code to enter DxeCore

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#include "DxeIpl.h"

+

+VOID

+EnterDxeMain (

+  IN VOID *StackTop,

+  IN VOID *DxeCoreEntryPoint,

+  IN VOID *Hob,

+  IN VOID *PageTable

+  )

+{

+  AsmWriteCr3 ((UINTN) PageTable);

+  SwitchStack (

+    (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,

+    Hob,

+    NULL,

+    StackTop

+    );

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/Paging.c b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/Paging.c
new file mode 100644
index 0000000..3b4de18
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/Paging.c
@@ -0,0 +1,238 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Paging.c

+

+Abstract:

+

+Revision History:

+

+**/

+

+#include "HobGeneration.h"

+#include "VirtualMemory.h"

+

+//

+// Create 2M-page table

+// PML4 (47:39)

+// PDPTE (38:30)

+// PDE (29:21)

+//

+

+#define EFI_2M_PAGE_BITS_NUM    21

+#define EFI_MAX_ENTRY_BITS_NUM  9

+

+#define EFI_PAGE_SIZE_4K        0x1000

+#define EFI_PAGE_SIZE_2M        (1 << EFI_2M_PAGE_BITS_NUM)

+

+#ifndef MIN

+  #define MIN(a, b)               ((a) < (b) ? (a) : (b))

+#endif

+#define ENTRY_NUM(x)            ((UINTN)1 << (x))

+

+UINT8 gPML4BitsNum;

+UINT8 gPDPTEBitsNum;

+UINT8 gPDEBitsNum;

+

+UINTN gPageNum2M;

+UINTN gPageNum4K;

+

+VOID

+EnableNullPointerProtection (

+  UINT8                       *PageTable

+  )

+{

+  X64_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB;

+

+  PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *) (PageTable + gPageNum2M * EFI_PAGE_SIZE_4K);

+  //

+  // Fill in the Page Table entries

+  // Mark 0~4K as not present

+  //

+  PageTableEntry4KB->Bits.Present = 0;

+

+  return ;

+}

+

+VOID

+X64Create4KPageTables (

+  UINT8                       *PageTable

+  )

+/*++

+Routine Description:

+  Create 4K-Page-Table for the low 2M memory.

+  This will change the previously created 2M-Page-Table-Entry.

+--*/

+{

+  UINT64                                        PageAddress;

+  UINTN                                         PTEIndex;

+  X64_PAGE_DIRECTORY_ENTRY_4K                   *PageDirectoryEntry4KB;

+  X64_PAGE_TABLE_ENTRY_4K                       *PageTableEntry4KB;

+

+  //

+  //  Page Table structure 4 level 4K.

+  //

+  //                   PageMapLevel4Entry        : bits 47-39

+  //                   PageDirectoryPointerEntry : bits 38-30

+  //  Page Table 4K  : PageDirectoryEntry4K      : bits 29-21

+  //                   PageTableEntry            : bits 20-12

+  //

+

+  PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *)(PageTable + gPageNum2M * EFI_PAGE_SIZE_4K);

+

+  PageDirectoryEntry4KB = (X64_PAGE_DIRECTORY_ENTRY_4K *) (PageTable + 2 * EFI_PAGE_SIZE_4K);

+  PageDirectoryEntry4KB->Uint64 = (UINT64)(UINTN)PageTableEntry4KB;

+  PageDirectoryEntry4KB->Bits.ReadWrite = 1;

+  PageDirectoryEntry4KB->Bits.Present = 1;

+  PageDirectoryEntry4KB->Bits.MustBeZero = 0;

+

+  for (PTEIndex = 0, PageAddress = 0; 

+       PTEIndex < ENTRY_NUM (EFI_MAX_ENTRY_BITS_NUM); 

+       PTEIndex++, PageTableEntry4KB++, PageAddress += EFI_PAGE_SIZE_4K

+      ) {

+    //

+    // Fill in the Page Table entries

+    //

+    PageTableEntry4KB->Uint64 = (UINT64)PageAddress;

+    PageTableEntry4KB->Bits.ReadWrite = 1;

+    PageTableEntry4KB->Bits.Present = 1;

+  }

+

+  return ;

+}

+

+VOID

+X64Create2MPageTables (

+  UINT8 *PageTable

+  )

+{

+  UINT64                                        PageAddress;

+  UINT8                                         *TempPageTable;

+  UINTN                                         PML4Index;

+  UINTN                                         PDPTEIndex;

+  UINTN                                         PDEIndex;

+  X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K     *PageMapLevel4Entry;

+  X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K     *PageDirectoryPointerEntry;

+  X64_PAGE_TABLE_ENTRY_2M                       *PageDirectoryEntry2MB;

+

+  TempPageTable = PageTable;

+  PageAddress   = 0;

+

+  //

+  //  Page Table structure 3 level 2MB.

+  //

+  //                   PageMapLevel4Entry        : bits 47-39

+  //                   PageDirectoryPointerEntry : bits 38-30

+  //  Page Table 2MB : PageDirectoryEntry2M      : bits 29-21

+  //

+

+  PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable;

+

+  for (PML4Index = 0; PML4Index < ENTRY_NUM (gPML4BitsNum); PML4Index++, PageMapLevel4Entry++) {

+    //

+    // Each PML4 entry points to a page of Page Directory Pointer entires.

+    //  

+    TempPageTable += EFI_PAGE_SIZE_4K;

+    PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable;

+

+    //

+    // Make a PML4 Entry

+    //

+    PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)(TempPageTable);

+    PageMapLevel4Entry->Bits.ReadWrite = 1;

+    PageMapLevel4Entry->Bits.Present = 1;

+

+    for (PDPTEIndex = 0; PDPTEIndex < ENTRY_NUM (gPDPTEBitsNum); PDPTEIndex++, PageDirectoryPointerEntry++) {

+      //

+      // Each Directory Pointer entries points to a page of Page Directory entires.

+      //       

+      TempPageTable += EFI_PAGE_SIZE_4K;

+      PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)TempPageTable;

+

+      //

+      // Fill in a Page Directory Pointer Entries

+      //

+      PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)(TempPageTable);

+      PageDirectoryPointerEntry->Bits.ReadWrite = 1;

+      PageDirectoryPointerEntry->Bits.Present = 1;

+

+      for (PDEIndex = 0; PDEIndex < ENTRY_NUM (gPDEBitsNum); PDEIndex++, PageDirectoryEntry2MB++) {

+        //

+        // Fill in the Page Directory entries

+        //

+        PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;

+        PageDirectoryEntry2MB->Bits.ReadWrite = 1;

+        PageDirectoryEntry2MB->Bits.Present = 1;

+        PageDirectoryEntry2MB->Bits.MustBe1 = 1;

+

+        PageAddress += EFI_PAGE_SIZE_2M;

+      }

+    }

+  }

+

+  return ;

+}

+

+VOID *

+PreparePageTable (

+  VOID  *PageNumberTop,

+  UINT8 SizeOfMemorySpace

+  )

+/*++

+Description:

+  Generate pagetable below PageNumberTop, 

+  and return the bottom address of pagetable for putting other things later.

+--*/

+{

+  VOID  *PageNumberBase;

+

+  SizeOfMemorySpace -= EFI_2M_PAGE_BITS_NUM;

+  gPDEBitsNum        = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM);

+  SizeOfMemorySpace  = (UINT8) (SizeOfMemorySpace - gPDEBitsNum);

+  gPDPTEBitsNum      = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM);

+  SizeOfMemorySpace  = (UINT8) (SizeOfMemorySpace - gPDPTEBitsNum);

+  gPML4BitsNum       = SizeOfMemorySpace;

+  if (gPML4BitsNum > EFI_MAX_ENTRY_BITS_NUM) {

+    return NULL;

+  }

+

+  //

+  // Suppose we have:

+  // 2MPage:

+  //   Entry:       PML4   ->     PDPTE     ->     PDE    -> Page

+  //   EntryNum:     a              b               c

+  // then

+  //   Occupy4KPage: 1              a              a*b

+  // 

+  // 2M 4KPage:

+  //   Entry:       PTE    ->     Page

+  //   EntryNum:    512

+  // then

+  //   Occupy4KPage: 1

+  //   

+

+  gPageNum2M = 1 + ENTRY_NUM (gPML4BitsNum) + ENTRY_NUM (gPML4BitsNum + gPDPTEBitsNum);

+  gPageNum4K = 1;

+

+

+  PageNumberBase = (VOID *)((UINTN)PageNumberTop - (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K);

+  ZeroMem (PageNumberBase, (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K);

+

+  X64Create2MPageTables (PageNumberBase);

+  X64Create4KPageTables (PageNumberBase);

+  //

+  // Not enable NULL Pointer Protection if using INTx call

+  //

+//  EnableNullPointerProtection (PageNumberBase);

+

+  return PageNumberBase;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/VirtualMemory.h b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/VirtualMemory.h
new file mode 100644
index 0000000..204f04e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/DxeIpl/X64/VirtualMemory.h
@@ -0,0 +1,117 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  VirtualMemory.h

+

+Abstract:

+

+Revision History:

+

+**/

+  

+#ifndef _VIRTUAL_MEMORY_H_

+#define _VIRTUAL_MEMORY_H_

+

+#pragma pack(1)

+

+//

+// Page Map Level 4 Offset (PML4) and

+// Page Directory Pointer Table (PDPE) entries 4K & 2M

+//

+

+typedef union {

+  struct {

+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT64  Reserved:1;               // Reserved

+    UINT64  MustBeZero:2;             // Must Be Zero

+    UINT64  Available:3;              // Available for use by system software

+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address

+    UINT64  AvabilableHigh:11;        // Available for use by system software

+    UINT64  Nx:1;                     // No Execute bit

+  } Bits;

+  UINT64    Uint64;

+} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;

+

+//

+// Page Directory Entry 4K

+//

+typedef union {

+  struct {

+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT64  MustBeZero:3;             // Must Be Zero

+    UINT64  Available:3;              // Available for use by system software

+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address

+    UINT64  AvabilableHigh:11;        // Available for use by system software

+    UINT64  Nx:1;                     // No Execute bit

+  } Bits;

+  UINT64    Uint64;

+} X64_PAGE_DIRECTORY_ENTRY_4K;

+

+//

+// Page Table Entry 4K

+//

+typedef union {

+  struct {

+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page

+    UINT64  PAT:1;                    // 0 = Ignore Page Attribute Table 

+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write

+    UINT64  Available:3;              // Available for use by system software

+    UINT64  PageTableBaseAddress:40;  // Page Table Base Address

+    UINT64  AvabilableHigh:11;        // Available for use by system software

+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution

+  } Bits;

+  UINT64    Uint64;

+} X64_PAGE_TABLE_ENTRY_4K;

+

+//

+// Page Table Entry 2M

+//

+typedef union {

+  struct {

+    UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory

+    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write

+    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User

+    UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching

+    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached

+    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)

+    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page

+    UINT64  MustBe1:1;                // Must be 1 

+    UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write

+    UINT64  Available:3;              // Available for use by system software

+    UINT64  PAT:1;                    //

+    UINT64  MustBeZero:8;             // Must be zero;

+    UINT64  PageTableBaseAddress:31;  // Page Table Base Address

+    UINT64  AvabilableHigh:11;        // Available for use by system software

+    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution

+  } Bits;

+  UINT64    Uint64;

+} X64_PAGE_TABLE_ENTRY_2M;

+

+#pragma pack()

+

+#endif 

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.c
new file mode 100644
index 0000000..84b2772
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.c
@@ -0,0 +1,79 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Debug.c

+

+Abstract:

+

+Revision History:

+

+--*/

+#include "EfiLdr.h"

+#include "Debug.h"

+

+UINT8 *mCursor;

+UINT8 mHeaderIndex = 10;

+

+

+VOID

+PrintHeader (

+  CHAR8 Char

+  )

+{

+  *(UINT8 *)(UINTN)(0x000b8000 + mHeaderIndex) = Char;

+  mHeaderIndex += 2;

+}

+

+VOID

+ClearScreen (

+  VOID

+  )

+{

+  UINT32 Index;

+

+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);

+  for (Index = 0; Index < 80 * 49; Index++) {

+    *mCursor = ' ';

+    mCursor += 2;

+  }

+  mCursor = (UINT8 *)(UINTN)(0x000b8000 + 160);

+}

+

+VOID

+PrintString (

+  IN CONST CHAR8  *FormatString,

+  ...

+  )

+{

+  UINTN           Index;

+  CHAR8           PrintBuffer[256];

+  VA_LIST         Marker;

+

+  VA_START (Marker, FormatString);

+  AsciiVSPrint (PrintBuffer, sizeof (PrintBuffer), FormatString, Marker);

+  VA_END (Marker);

+

+  for (Index = 0; PrintBuffer[Index] != 0; Index++) {

+    if (PrintBuffer[Index] == '\n') {

+      mCursor = (UINT8 *) (UINTN) (0xb8000 + (((((UINTN)mCursor - 0xb8000) + 160) / 160) * 160));

+    } else {

+      *mCursor = (UINT8) PrintBuffer[Index];

+      mCursor += 2;

+    }

+  }

+

+  //

+  // All information also output to serial port.

+  //

+  SerialPortWrite ((UINT8 *) PrintBuffer, Index);

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.h
new file mode 100644
index 0000000..f6aa7a2
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/Debug.h
@@ -0,0 +1,40 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Debug.h

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#ifndef _EFILDR_DEBUG_H_

+#define _EFILDR_DEBUG_H_

+

+VOID

+PrintHeader (

+  CHAR8 Char

+  );

+

+VOID

+PrintString (

+  IN CONST CHAR8  *FormatString,

+  ...

+  );

+

+VOID 

+ClearScreen (

+  VOID

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.h
new file mode 100644
index 0000000..665f405
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.h
@@ -0,0 +1,92 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  EfiLdr.c

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#ifndef _DUET_EFI_LOADER_H_

+#define _DUET_EFI_LOADER_H_

+

+#include "Uefi.h"

+#include "EfiLdrHandoff.h"

+

+#include <Protocol/LoadedImage.h>

+#include <IndustryStandard/PeImage.h>

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/PrintLib.h>

+#include <Library/SerialPortLib.h>

+

+#define INT15_E820_AddressRangeMemory   1

+#define INT15_E820_AddressRangeReserved 2

+#define INT15_E820_AddressRangeACPI     3

+#define INT15_E820_AddressRangeNVS      4

+

+#define EFI_FIRMWARE_BASE_ADDRESS  0x00200000

+

+#define EFI_DECOMPRESSED_BUFFER_ADDRESS 0x00600000

+

+#define EFI_MAX_MEMORY_DESCRIPTORS 64

+

+#define LOADED_IMAGE_SIGNATURE     SIGNATURE_32('l','d','r','i')

+

+typedef struct {

+  UINTN                       Signature;

+  CHAR16                      *Name;          // Displayable name

+  UINTN                       Type;

+

+  BOOLEAN                     Started;        // If entrypoint has been called

+  VOID                        *StartImageContext;

+

+  EFI_IMAGE_ENTRY_POINT       EntryPoint;     // The image's entry point

+  EFI_LOADED_IMAGE_PROTOCOL   Info;           // loaded image protocol

+

+  // 

+  EFI_PHYSICAL_ADDRESS        ImageBasePage;  // Location in memory

+  UINTN                       NoPages;        // Number of pages 

+  UINT8                       *ImageBase;     // As a char pointer

+  UINT8                       *ImageEof;      // End of memory image

+

+  // relocate info

+  UINT8                       *ImageAdjust;   // Bias for reloc calculations

+  UINTN                       StackAddress;

+  UINT8                       *FixupData;     //  Original fixup data

+} EFILDR_LOADED_IMAGE;

+

+#pragma pack(4)

+typedef struct {          

+  UINT64       BaseAddress;

+  UINT64       Length;

+  UINT32       Type;

+} BIOS_MEMORY_MAP_ENTRY;

+#pragma pack()

+

+typedef struct {          

+  UINT32                MemoryMapSize;

+  BIOS_MEMORY_MAP_ENTRY MemoryMapEntry[1];

+} BIOS_MEMORY_MAP;

+

+EFILDR_LOADED_IMAGE    DxeCoreImage;

+EFILDR_LOADED_IMAGE    DxeIplImage;

+

+typedef

+VOID

+(EFIAPI * EFI_MAIN_ENTRYPOINT) (

+    IN EFILDRHANDOFF  *Handoff

+    );

+

+#endif //_DUET_EFI_LOADER_H_

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.inf b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.inf
new file mode 100644
index 0000000..b5a46db
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdr.inf
@@ -0,0 +1,55 @@
+## @file

+# 

+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#  Module Name:

+#    EfiLdr.inf

+#

+#  Abstract:

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = EfiLoader

+  FILE_GUID                      = A9620E5C-5FA1-40b7-8B21-50B632F88F38

+  MODULE_TYPE                    = UEFI_APPLICATION

+  VERSION_STRING                 = 1.0

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec

+

+[LibraryClasses]

+  BaseLib

+  BaseMemoryLib

+  PrintLib

+  SerialPortLib

+

+[Sources]

+  Debug.h

+  PeLoader.h

+  Support.h

+  EfiLdrHandoff.h

+  EfiLdr.h

+  EfiLoader.c

+  Debug.c

+  PeLoader.c

+  Support.c

+  #TianoDecompress.c

+  #TianoDecompress.h

+  LzmaDecompress.h

+

+[Guids]

+  gTianoCustomDecompressGuid

+

+[BuildOptions]

+  MSFT:*_*_*_DLINK_FLAGS = /BASE:0x10000

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdrHandoff.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdrHandoff.h
new file mode 100644
index 0000000..3e5210f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLdrHandoff.h
@@ -0,0 +1,56 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  EfiLdrHandoff.h

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#ifndef _EFILDR_HANDOFF_H_

+#define _EFILDR_HANDOFF_H_

+

+#define EFILDR_BASE_SEGMENT 0x2000

+#define EFILDR_LOAD_ADDRESS        (EFILDR_BASE_SEGMENT << 4)

+#define EFILDR_HEADER_ADDRESS      (EFILDR_LOAD_ADDRESS+0x2000)

+

+#define EFILDR_CB_VA        0x00

+

+typedef struct _EFILDRHANDOFF {

+    UINTN                    MemDescCount;

+    EFI_MEMORY_DESCRIPTOR   *MemDesc;

+    VOID                    *BfvBase;

+    UINTN                   BfvSize;

+    VOID                    *DxeIplImageBase;

+    UINTN                   DxeIplImageSize;

+    VOID                    *DxeCoreImageBase;

+    UINTN                   DxeCoreImageSize;

+    VOID                    *DxeCoreEntryPoint;

+} EFILDRHANDOFF;

+

+typedef struct {

+    UINT32       CheckSum;

+    UINT32       Offset;

+    UINT32       Length;

+    UINT8        FileName[52];

+} EFILDR_IMAGE;

+

+typedef struct {          

+    UINT32       Signature;     

+    UINT32       HeaderCheckSum;

+    UINT32       FileLength;

+    UINT32       NumberOfImages;

+} EFILDR_HEADER;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLoader.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLoader.c
new file mode 100644
index 0000000..6913027
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/EfiLoader.c
@@ -0,0 +1,291 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  EfiLoader.c

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#include "EfiLdr.h"

+#include "Support.h"

+#include "Debug.h"

+#include "PeLoader.h"

+#include "LzmaDecompress.h"

+

+VOID

+SystemHang (

+  CHAR8        *Message

+  )

+{

+  PrintString (

+    "%s## FATAL ERROR ##: Fail to load DUET images! System hang!\n",

+    Message

+    );

+  CpuDeadLoop();

+}

+

+VOID

+EfiLoader (

+  UINT32    BiosMemoryMapBaseAddress

+  )

+{

+  BIOS_MEMORY_MAP       *BiosMemoryMap;    

+  EFILDR_IMAGE          *EFILDRImage;

+  EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS];

+  EFI_STATUS            Status;

+  UINTN                 NumberOfMemoryMapEntries;

+  UINT32                DestinationSize;

+  UINT32                ScratchSize;

+  UINTN                 BfvPageNumber;

+  UINTN                 BfvBase;

+  EFI_MAIN_ENTRYPOINT   EfiMainEntrypoint;

+  EFILDRHANDOFF         Handoff;

+  UINTN                 Index;

+

+  ClearScreen();

+  

+  PrintHeader ('A');

+  

+  PrintString ("Enter DUET Loader...\n");

+  PrintString ("BiosMemoryMapBaseAddress = %x\n", (UINTN) BiosMemoryMapBaseAddress);

+

+  //

+  // Add all EfiConventionalMemory descriptors to the table.  If there are partial pages, then

+  // round the start address up to the next page, and round the length down to a page boundry.

+  //

+  BiosMemoryMap = (BIOS_MEMORY_MAP *) (UINTN) BiosMemoryMapBaseAddress;

+  NumberOfMemoryMapEntries = 0;

+  GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap);

+

+  PrintString ("Get %d entries of memory map!\n", NumberOfMemoryMapEntries);

+

+  //

+  // Get information on where the image is in memory

+  //

+  EFILDRImage  = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER));

+

+

+  //

+  // Point to the 4th image (Bfv)

+  //

+  EFILDRImage += 3;

+

+  //

+  // Decompress the image

+  //

+  PrintString (

+    "Decompress BFV image, Image Address = %x Offset = %x\n", 

+    (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+    (UINTN) EFILDRImage->Offset

+    );

+  Status = LzmaUefiDecompressGetInfo (

+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+             EFILDRImage->Length,

+             &DestinationSize, 

+             &ScratchSize

+             );

+

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to get decompress information for BFV!\n");

+  }

+  

+  PrintString ("BFV decompress: DestinationSize = %x, ScratchSize = %x\n", (UINTN) DestinationSize, (UINTN) ScratchSize);

+  Status =  LzmaUefiDecompress (

+    (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+    EFILDRImage->Length,

+    (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, 

+    (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)

+    );

+  

+

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to decompress BFV!\n");

+  }

+

+  BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize);

+  BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);

+  if (BfvBase == 0) {

+    SystemHang ("Failed to find free space to hold decompressed BFV\n");

+  }

+  ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE);

+  CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize);

+

+  PrintHeader ('B');

+

+  //

+  // Point to the 2nd image (DxeIpl)

+  //

+    

+  EFILDRImage -= 2;

+

+  //

+  // Decompress the image

+  //

+  PrintString (

+    "Decompress DxeIpl image, Image Address = %x Offset = %x\n", 

+    (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+    (UINTN) EFILDRImage->Offset

+    );

+

+  Status = LzmaUefiDecompressGetInfo (

+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+             EFILDRImage->Length,

+             &DestinationSize, 

+             &ScratchSize

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to get decompress information for DxeIpl!\n");

+  }

+

+  Status = LzmaUefiDecompress (

+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+             EFILDRImage->Length,

+             (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,

+             (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to decompress DxeIpl image\n");

+  }

+

+  PrintString ("Start load DxeIpl PE image\n");  

+

+  //

+  // Load and relocate the EFI PE/COFF Firmware Image 

+  //

+  Status = EfiLdrPeCoffLoadPeImage (

+             (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), 

+             &DxeIplImage, 

+             &NumberOfMemoryMapEntries, 

+             EfiMemoryDescriptor

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to load and relocate DxeIpl PE image!\n");

+  }

+  PrintString (

+    "DxeIpl PE image is successed loaded at %lx, entry=%p\n",

+    DxeIplImage.ImageBasePage,

+    DxeIplImage.EntryPoint

+    );

+

+PrintHeader ('C');

+

+  //

+  // Point to the 3rd image (DxeMain)

+  //

+  EFILDRImage++;

+

+  //

+  // Decompress the image

+  //

+  PrintString (

+    "Decompress DxeMain FV image, Image Address = %x Offset = %x\n",

+    (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+    (UINTN) EFILDRImage->Offset

+    );

+

+  Status = LzmaUefiDecompressGetInfo (

+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+             EFILDRImage->Length,

+             &DestinationSize, 

+             &ScratchSize

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to get decompress information for DxeMain FV image!\n");

+  }

+

+  Status = LzmaUefiDecompress (

+             (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset),

+              EFILDRImage->Length,

+             (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS,

+             (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000)

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to decompress DxeMain FV image!\n");

+  }

+

+  //

+  // Load and relocate the EFI PE/COFF Firmware Image 

+  //

+  Status = EfiLdrPeCoffLoadPeImage (

+             (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), 

+             &DxeCoreImage, 

+             &NumberOfMemoryMapEntries, 

+             EfiMemoryDescriptor

+             );

+  if (EFI_ERROR (Status)) {

+    SystemHang ("Failed to load/relocate DxeMain!\n");

+  }

+  PrintString (

+    "DxeCore PE image is successed loaded at %lx, entry=%p\n",

+    DxeCoreImage.ImageBasePage,

+    DxeCoreImage.EntryPoint

+    );

+

+PrintHeader ('E');

+

+  //

+  // Display the table of memory descriptors.

+  //

+  PrintString ("\nEFI Memory Descriptors\n");   

+  for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) {

+    PrintString (

+      "Type = %x Start = %08lx NumberOfPages = %08lx\n",

+      EfiMemoryDescriptor[Index].Type, EfiMemoryDescriptor[Index].PhysicalStart, EfiMemoryDescriptor[Index].NumberOfPages

+      );

+  }

+

+  //

+  // Jump to EFI Firmware

+  //

+

+  if (DxeIplImage.EntryPoint != NULL) {

+

+    Handoff.MemDescCount      = NumberOfMemoryMapEntries;

+    Handoff.MemDesc           = EfiMemoryDescriptor;

+    Handoff.BfvBase           = (VOID *)(UINTN)BfvBase;

+    Handoff.BfvSize           = BfvPageNumber * EFI_PAGE_SIZE;

+    Handoff.DxeIplImageBase   = (VOID *)(UINTN)DxeIplImage.ImageBasePage;

+    Handoff.DxeIplImageSize   = DxeIplImage.NoPages * EFI_PAGE_SIZE;

+    Handoff.DxeCoreImageBase  = (VOID *)(UINTN)DxeCoreImage.ImageBasePage;

+    Handoff.DxeCoreImageSize  = DxeCoreImage.NoPages * EFI_PAGE_SIZE;

+    Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint;

+

+    PrintString ("Transfer to DxeIpl ...EntryPoint = %p\n", DxeIplImage.EntryPoint);

+    

+    EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT) DxeIplImage.EntryPoint;

+    EfiMainEntrypoint (&Handoff);

+  }

+

+PrintHeader ('F');

+

+  //

+  // There was a problem loading the image, so HALT the system.

+  //

+

+  SystemHang ("Failed to jump to DxeIpl!\n");

+}

+

+EFI_STATUS

+EFIAPI

+_ModuleEntryPoint (

+  UINT32    BiosMemoryMapBaseAddress

+  )

+{

+  SerialPortInitialize ();

+  EfiLoader(BiosMemoryMapBaseAddress);

+  return EFI_SUCCESS;

+}

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/LzmaDecompress.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/LzmaDecompress.h
new file mode 100644
index 0000000..7d20fda
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/LzmaDecompress.h
@@ -0,0 +1,70 @@
+/** @file

+  LZMA Decompress Library header file

+

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

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#ifndef __LZMADECOMPRESS_H__

+#define __LZMADECOMPRESS_H__

+

+/**

+  The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().

+  

+  @param Source           The source buffer containing the compressed data.

+  @param SourceSize       The size of source buffer

+  @param DestinationSize  The size of destination buffer.

+  @param ScratchSize      The size of scratch buffer.

+

+  @retval RETURN_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  @retval RETURN_INVALID_PARAMETER - The source data is corrupted

+**/

+RETURN_STATUS

+EFIAPI

+LzmaUefiDecompressGetInfo (

+  IN  CONST VOID  *Source,

+  IN  UINT32      SourceSize,

+  OUT UINT32      *DestinationSize,

+  OUT UINT32      *ScratchSize

+  );

+

+/**

+  Decompresses a Lzma compressed source buffer.

+

+  Extracts decompressed data to its original form.

+  If the compressed source data specified by Source is successfully decompressed 

+  into Destination, then RETURN_SUCCESS is returned.  If the compressed source data 

+  specified by Source is not in a valid compressed data format,

+  then RETURN_INVALID_PARAMETER is returned.

+

+  @param  Source      The source buffer containing the compressed data.

+  @param  SourceSize  The size of source buffer.

+  @param  Destination The destination buffer to store the decompressed data

+  @param  Scratch     A temporary scratch buffer that is used to perform the decompression.

+                      This is an optional parameter that may be NULL if the 

+                      required scratch buffer size is 0.

+                     

+  @retval  RETURN_SUCCESS Decompression completed successfully, and 

+                          the uncompressed buffer is returned in Destination.

+  @retval  RETURN_INVALID_PARAMETER 

+                          The source buffer specified by Source is corrupted 

+                          (not in a valid compressed format).

+**/

+RETURN_STATUS

+EFIAPI

+LzmaUefiDecompress (

+  IN CONST VOID  *Source,

+  IN UINTN       SourceSize,

+  IN OUT VOID    *Destination,

+  IN OUT VOID    *Scratch

+  );

+  

+#endif // __LZMADECOMPRESS_H__

+

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.c
new file mode 100644
index 0000000..7fafdfb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.c
@@ -0,0 +1,641 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PeLoader.c

+

+Abstract:

+

+Revision History:

+

+--*/

+#include "EfiLdr.h"

+#include "Debug.h"

+#include "Support.h"

+

+EFI_STATUS

+EfiLdrPeCoffLoadPeRelocate (

+  IN EFILDR_LOADED_IMAGE      *Image,

+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,

+  IN UINTN                     Adjust,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  );

+

+EFI_STATUS

+EfiLdrPeCoffImageRead (

+    IN VOID                 *FHand,

+    IN UINTN                Offset,

+    IN OUT UINTN            ReadSize,

+    OUT VOID                *Buffer

+    );

+

+VOID *

+EfiLdrPeCoffImageAddress (

+  IN EFILDR_LOADED_IMAGE     *Image,

+  IN UINTN                   Address

+  );

+

+

+EFI_STATUS

+EfiLdrPeCoffSetImageType (

+  IN OUT EFILDR_LOADED_IMAGE      *Image,

+  IN UINTN                        ImageType

+  );

+

+EFI_STATUS

+EfiLdrPeCoffCheckImageMachineType (

+  IN UINT16           MachineType

+  );

+

+EFI_STATUS

+EfiLdrGetPeImageInfo (

+  IN  VOID                    *FHand,

+  OUT UINT64                  *ImageBase,

+  OUT UINT32                  *ImageSize

+  )

+{

+  EFI_STATUS                        Status;

+  EFI_IMAGE_DOS_HEADER              DosHdr;

+  EFI_IMAGE_OPTIONAL_HEADER_UNION   PeHdr;

+

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

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

+

+  //

+  // Read image headers

+  //

+

+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);

+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    return EFI_UNSUPPORTED;

+  }

+

+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);

+

+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {

+    return EFI_UNSUPPORTED;

+  }

+    

+  //

+  // Verify machine type

+  //

+

+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);

+  if (EFI_ERROR(Status)) {

+    return Status;

+  }

+

+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    *ImageBase = (UINT32)PeHdr.Pe32.OptionalHeader.ImageBase;

+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {

+    *ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;

+  } else {

+    return EFI_UNSUPPORTED;

+  }

+  

+  *ImageSize = PeHdr.Pe32.OptionalHeader.SizeOfImage;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EfiLdrPeCoffLoadPeImage (

+  IN VOID                     *FHand,

+  IN EFILDR_LOADED_IMAGE      *Image,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  )

+{

+  EFI_IMAGE_DOS_HEADER            DosHdr;

+  EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;

+  EFI_IMAGE_SECTION_HEADER        *FirstSection;

+  EFI_IMAGE_SECTION_HEADER        *Section;

+  UINTN                           Index;

+  EFI_STATUS                      Status;

+  UINT8                           *Base;

+  UINT8                           *End;

+  EFI_IMAGE_DATA_DIRECTORY        *DirectoryEntry;

+  UINTN                           DirCount;

+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY TempDebugEntry;

+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;

+  UINTN                           CodeViewSize;

+  UINTN                           CodeViewOffset;

+  UINTN                           CodeViewFileOffset;

+  UINTN                           OptionalHeaderSize;

+  UINTN                           PeHeaderSize;

+  UINT32                          NumberOfRvaAndSizes;

+  EFI_IMAGE_DATA_DIRECTORY        *DataDirectory;

+  UINT64                          ImageBase;

+  CHAR8                           PrintBuffer[256];

+

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

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

+

+  //

+  // Read image headers

+  //

+

+  EfiLdrPeCoffImageRead (FHand, 0, sizeof(DosHdr), &DosHdr);

+  if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) {

+    AsciiSPrint (PrintBuffer, 256, "PeCoffLoadPeImage: Dos header signature not found\n");

+    PrintString (PrintBuffer);

+    PrintHeader ('F');

+    return EFI_UNSUPPORTED;

+  }

+

+  EfiLdrPeCoffImageRead (FHand, DosHdr.e_lfanew, sizeof(PeHdr), &PeHdr);

+

+  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {

+    AsciiSPrint (PrintBuffer, 256, "PeCoffLoadPeImage: PE image header signature not found\n");

+    PrintString (PrintBuffer);

+    PrintHeader ('G');

+    return EFI_UNSUPPORTED;

+  }

+    

+  //

+  // Set the image subsystem type

+  //

+

+  Status = EfiLdrPeCoffSetImageType (Image, PeHdr.Pe32.OptionalHeader.Subsystem);

+  if (EFI_ERROR(Status)) {

+    AsciiSPrint (PrintBuffer, 256, "PeCoffLoadPeImage: Subsystem type not known\n");

+    PrintString (PrintBuffer);

+    PrintHeader ('H');

+    return Status;

+  }

+

+  //

+  // Verify machine type

+  //

+

+  Status = EfiLdrPeCoffCheckImageMachineType (PeHdr.Pe32.FileHeader.Machine);

+  if (EFI_ERROR(Status)) {

+    AsciiSPrint (PrintBuffer, 256, "PeCoffLoadPeImage: Incorrect machine type\n");

+    PrintString (PrintBuffer);

+    PrintHeader ('I');

+    return Status;

+  }

+

+  //

+  // Compute the amount of memory needed to load the image and 

+  // allocate it.  This will include all sections plus the codeview debug info.

+  // Since the codeview info is actually outside of the image, we calculate

+  // its size seperately and add it to the total.

+  //

+  // Memory starts off as data

+  //

+

+  CodeViewSize       = 0;

+  CodeViewFileOffset = 0;

+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);

+  } else if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {

+    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(PeHdr.Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);

+  } else {

+    return EFI_UNSUPPORTED;

+  }

+  for (DirCount = 0; 

+       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && (CodeViewSize == 0);

+       DirCount++) {

+    Status = EfiLdrPeCoffImageRead (

+               FHand, 

+               DirectoryEntry->VirtualAddress + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),

+               sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY),

+               &TempDebugEntry

+               );

+    if (!EFI_ERROR (Status)) {

+      if (TempDebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {

+        CodeViewSize = TempDebugEntry.SizeOfData;

+        CodeViewFileOffset = TempDebugEntry.FileOffset;

+      }

+    }

+  }

+    

+  CodeViewOffset = PeHdr.Pe32.OptionalHeader.SizeOfImage + PeHdr.Pe32.OptionalHeader.SectionAlignment;

+  Image->NoPages = EFI_SIZE_TO_PAGES (CodeViewOffset + CodeViewSize);

+

+  //

+  // Compute the amount of memory needed to load the image and 

+  // allocate it.  Memory starts off as data

+  //

+

+  Image->ImageBasePage = (EFI_PHYSICAL_ADDRESS)FindSpace (Image->NoPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesCode, EFI_MEMORY_WB);

+  if (Image->ImageBasePage == 0) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  if (EFI_ERROR(Status)) {

+    PrintHeader ('J');

+    return Status;

+  }

+

+  AsciiSPrint (PrintBuffer, 256, "LoadPe: new image base %lx\n", Image->ImageBasePage);

+  PrintString (PrintBuffer);

+  Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageBasePage;

+  Image->Info.ImageSize = (Image->NoPages << EFI_PAGE_SHIFT) - 1;

+  Image->ImageBase      = (UINT8 *)(UINTN)Image->ImageBasePage;

+  Image->ImageEof       = Image->ImageBase + Image->Info.ImageSize;

+  Image->ImageAdjust    = Image->ImageBase;

+

+  //

+  // Copy the Image header to the base location

+  //

+  Status = EfiLdrPeCoffImageRead (

+             FHand, 

+             0, 

+             PeHdr.Pe32.OptionalHeader.SizeOfHeaders, 

+             Image->ImageBase

+             );

+

+  if (EFI_ERROR(Status)) {

+    PrintHeader ('K');

+    return Status;

+  }

+

+  //

+  // Load each directory of the image into memory... 

+  //  Save the address of the Debug directory for later

+  //

+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    NumberOfRvaAndSizes = PeHdr.Pe32.OptionalHeader.NumberOfRvaAndSizes;

+    DataDirectory = PeHdr.Pe32.OptionalHeader.DataDirectory;

+  } else {

+    NumberOfRvaAndSizes = PeHdr.Pe32Plus.OptionalHeader.NumberOfRvaAndSizes;

+    DataDirectory = PeHdr.Pe32Plus.OptionalHeader.DataDirectory;

+  }

+  DebugEntry = NULL;

+  for (Index = 0; Index < NumberOfRvaAndSizes; Index++) {

+    if ((DataDirectory[Index].VirtualAddress != 0) && (DataDirectory[Index].Size != 0)) {

+      Status = EfiLdrPeCoffImageRead (

+                 FHand,

+                 DataDirectory[Index].VirtualAddress,

+                 DataDirectory[Index].Size,

+                 Image->ImageBase + DataDirectory[Index].VirtualAddress

+                 );

+      if (EFI_ERROR(Status)) {

+        return Status;

+      }

+      if (Index == EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {

+        DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (Image->ImageBase + DataDirectory[Index].VirtualAddress);

+      }

+    }

+  }

+

+  //

+  // Load each section of the image

+  //

+

+  // BUGBUG: change this to use the in memory copy

+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER32);

+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS32);

+  } else {

+    OptionalHeaderSize = sizeof(EFI_IMAGE_OPTIONAL_HEADER64);

+    PeHeaderSize       = sizeof(EFI_IMAGE_NT_HEADERS64);

+  }

+  FirstSection = (EFI_IMAGE_SECTION_HEADER *) (

+                   Image->ImageBase +

+                   DosHdr.e_lfanew + 

+                   PeHeaderSize + 

+                   PeHdr.Pe32.FileHeader.SizeOfOptionalHeader - 

+                   OptionalHeaderSize

+                   );

+

+  Section = FirstSection;

+  for (Index=0; Index < PeHdr.Pe32.FileHeader.NumberOfSections; Index += 1) {

+

+    //

+    // Compute sections address

+    //

+

+    Base = EfiLdrPeCoffImageAddress (Image, (UINTN)Section->VirtualAddress);

+    End = EfiLdrPeCoffImageAddress (Image, (UINTN)(Section->VirtualAddress + Section->Misc.VirtualSize));

+        

+    if (EFI_ERROR(Status) || !Base || !End) {

+//      DEBUG((D_LOAD|D_ERROR, "LoadPe: Section %d was not loaded\n", Index));

+    PrintHeader ('L');

+      return EFI_LOAD_ERROR;

+    }

+

+//    DEBUG((D_LOAD, "LoadPe: Section %d, loaded at %x\n", Index, Base));

+

+    //

+    // Read the section

+    //

+ 

+    if (Section->SizeOfRawData) {

+      Status = EfiLdrPeCoffImageRead (FHand, Section->PointerToRawData, Section->SizeOfRawData, Base);

+      if (EFI_ERROR(Status)) {

+PrintHeader ('M');

+        return Status;

+      }

+    }

+

+    //

+    // If raw size is less then virt size, zero fill the remaining

+    //

+

+    if (Section->SizeOfRawData < Section->Misc.VirtualSize) {

+      ZeroMem (

+        Base + Section->SizeOfRawData, 

+        Section->Misc.VirtualSize - Section->SizeOfRawData

+        );

+    }

+

+    //

+    // Next Section

+    //

+

+    Section += 1;

+  }

+

+  //

+  // Copy in CodeView information if it exists

+  //

+  if (CodeViewSize != 0) {

+    Status = EfiLdrPeCoffImageRead (FHand, CodeViewFileOffset, CodeViewSize, Image->ImageBase + CodeViewOffset);

+    DebugEntry->RVA = (UINT32) (CodeViewOffset);

+  }

+

+  //

+  // Apply relocations only if needed

+  //

+  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

+    ImageBase = (UINT64)PeHdr.Pe32.OptionalHeader.ImageBase;

+  } else {

+    ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;

+  }

+  if ((UINTN)(Image->ImageBase) != (UINTN) (ImageBase)) {

+    Status = EfiLdrPeCoffLoadPeRelocate (

+               Image,

+               &DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC],

+               (UINTN) Image->ImageBase - (UINTN)ImageBase,

+               NumberOfMemoryMapEntries,

+               EfiMemoryDescriptor

+               );

+

+    if (EFI_ERROR(Status)) {

+      PrintHeader ('N');

+      return Status;

+    }

+  }

+

+  //

+  // Use exported EFI specific interface if present, else use the image's entry point

+  //

+  Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)

+                        (EfiLdrPeCoffImageAddress(

+                           Image, 

+                           PeHdr.Pe32.OptionalHeader.AddressOfEntryPoint

+                           ));

+

+  return Status;

+}

+

+EFI_STATUS

+EfiLdrPeCoffLoadPeRelocate (

+  IN EFILDR_LOADED_IMAGE      *Image,

+  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,

+  IN UINTN                     Adjust,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  )

+{

+  EFI_IMAGE_BASE_RELOCATION   *RelocBase;

+  EFI_IMAGE_BASE_RELOCATION   *RelocBaseEnd;

+  UINT16                      *Reloc;

+  UINT16                      *RelocEnd;

+  UINT8                       *Fixup;

+  UINT8                       *FixupBase;

+  UINT16                      *F16;

+  UINT32                      *F32;

+  UINT64                      *F64;

+  UINT8                       *FixupData;

+  UINTN                       NoFixupPages;

+

+  //

+  // Find the relocation block

+  //

+

+  RelocBase = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress);

+  RelocBaseEnd = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);

+  if (!RelocBase || !RelocBaseEnd) {

+PrintHeader ('O');

+    return EFI_LOAD_ERROR;

+  }

+

+  NoFixupPages = EFI_SIZE_TO_PAGES(RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));

+  Image->FixupData = (UINT8*) FindSpace (NoFixupPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);

+  if (Image->FixupData == 0) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  //

+  // Run the whole relocation block

+  //

+

+  FixupData = Image->FixupData;

+  while (RelocBase < RelocBaseEnd) {

+           

+    Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));

+    RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);

+    FixupBase = EfiLdrPeCoffImageAddress (Image, RelocBase->VirtualAddress);

+    if ((UINT8 *) RelocEnd < Image->ImageBase || (UINT8 *) RelocEnd > Image->ImageEof) {

+PrintHeader ('P');

+      return EFI_LOAD_ERROR;

+    }

+

+    //

+    // Run this relocation record

+    //

+

+    while (Reloc < RelocEnd) {

+

+      Fixup = FixupBase + (*Reloc & 0xFFF);

+      switch ((*Reloc) >> 12) {

+

+      case EFI_IMAGE_REL_BASED_ABSOLUTE:

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGH:

+        F16 = (UINT16 *) Fixup;

+        *F16  = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16));

+        if (FixupData != NULL) {

+          *(UINT16 *) FixupData = *F16;

+          FixupData = FixupData + sizeof(UINT16);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_LOW:

+        F16 = (UINT16 *) Fixup;

+        *F16 = (UINT16) (*F16 + (UINT16) Adjust);

+        if (FixupData != NULL) {

+          *(UINT16 *) FixupData = *F16;

+          FixupData = FixupData + sizeof(UINT16);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGHLOW:

+        F32 = (UINT32 *) Fixup;

+        *F32 = *F32 + (UINT32) Adjust;

+        if (FixupData != NULL) {

+          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));

+          *(UINT32 *) FixupData = *F32;

+          FixupData = FixupData + sizeof(UINT32);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_DIR64:

+        F64 = (UINT64 *) Fixup;

+        *F64 = *F64 + (UINT64) Adjust;

+        if (FixupData != NULL) {

+          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT64));

+          *(UINT64 *) FixupData = *F64;

+          FixupData = FixupData + sizeof(UINT64);

+        }

+        break;

+

+      case EFI_IMAGE_REL_BASED_HIGHADJ:

+        CpuDeadLoop();                 // BUGBUG: not done

+        break;

+

+      default:

+//        DEBUG((D_LOAD|D_ERROR, "PeRelocate: unknown fixed type\n"));

+PrintHeader ('Q');

+        CpuDeadLoop();

+        return EFI_LOAD_ERROR;

+      }

+

+      // Next reloc record

+      Reloc += 1;

+    }

+

+    // next reloc block

+    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;

+  }

+

+  //

+  // Add Fixup data to whole Image (assume Fixup data just below the image), so that there is no hole in the descriptor.

+  // Because only NoPages or ImageBasePage will be used in EfiLoader(), we update these 2 fields.

+  //

+  Image->NoPages += NoFixupPages;

+  Image->ImageBasePage -= (NoFixupPages << EFI_PAGE_SHIFT);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EfiLdrPeCoffImageRead (

+  IN VOID                 *FHand,

+  IN UINTN                Offset,

+  IN OUT UINTN            ReadSize,

+  OUT VOID                *Buffer

+  )

+{

+  CopyMem (Buffer, (VOID *)((UINTN)FHand + Offset), ReadSize);

+

+  return EFI_SUCCESS;

+}

+

+VOID *

+EfiLdrPeCoffImageAddress (

+  IN EFILDR_LOADED_IMAGE     *Image,

+  IN UINTN                   Address

+  )

+{

+  UINT8        *FixedAddress;

+

+  FixedAddress = Image->ImageAdjust + Address;

+

+  if ((FixedAddress < Image->ImageBase) || (FixedAddress > Image->ImageEof)) {

+//    DEBUG((D_LOAD|D_ERROR, "PeCoffImageAddress: pointer is outside of image\n"));

+    FixedAddress = NULL;

+  }

+

+//  DEBUG((

+//    D_LOAD,

+//    "PeCoffImageAddress: ImageBase %x, ImageEof %x, Address %x, FixedAddress %x\n", 

+//    Image->ImageBase,

+//    Image->ImageEof,

+//    Address,

+//    FixedAddress

+//    ));

+    return FixedAddress;

+}

+

+

+EFI_STATUS

+EfiLdrPeCoffSetImageType (

+  IN OUT EFILDR_LOADED_IMAGE      *Image,

+  IN UINTN                        ImageType

+  )

+{

+  EFI_MEMORY_TYPE                 CodeType;

+  EFI_MEMORY_TYPE                 DataType;

+

+  switch (ImageType) {

+  case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:

+    CodeType = EfiLoaderCode;

+    DataType = EfiLoaderData;

+    break;

+

+  case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:

+    CodeType = EfiBootServicesCode;

+    DataType = EfiBootServicesData;

+    break;

+

+  case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:

+    CodeType = EfiRuntimeServicesCode;

+    DataType = EfiRuntimeServicesData;

+    break;

+

+  default:

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Image->Type = ImageType;

+  Image->Info.ImageCodeType = CodeType;    

+  Image->Info.ImageDataType = DataType;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EfiLdrPeCoffCheckImageMachineType (

+  IN UINT16           MachineType

+  )

+{

+  EFI_STATUS          Status;

+

+  Status = EFI_UNSUPPORTED;

+

+#ifdef MDE_CPU_IA32

+  if (MachineType == EFI_IMAGE_MACHINE_IA32) {

+    Status = EFI_SUCCESS;

+  }

+#endif

+

+#ifdef MDE_CPU_X64

+  if (MachineType == EFI_IMAGE_MACHINE_X64) {

+    Status = EFI_SUCCESS;

+  }

+#endif

+

+#ifdef MDE_CPU_IPF

+  if (MachineType == EFI_IMAGE_MACHINE_IA64) {

+    Status = EFI_SUCCESS;

+  }

+#endif

+

+  return Status;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.h
new file mode 100644
index 0000000..c6c2398
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/PeLoader.h
@@ -0,0 +1,42 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PeLoader.h

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#ifndef _EFILDR_PELOADER_H_

+#define _EFILDR_PELOADER_H_

+

+#include "EfiLdr.h"

+

+EFI_STATUS

+EfiLdrGetPeImageInfo (

+  IN VOID                     *FHand,

+  OUT UINT64                  *ImageBase,

+  OUT UINT32                  *ImageSize

+  );

+

+EFI_STATUS

+EfiLdrPeCoffLoadPeImage (

+  IN VOID                     *FHand,

+  IN EFILDR_LOADED_IMAGE      *Image,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor

+  );

+

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.c
new file mode 100644
index 0000000..a0c9046
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.c
@@ -0,0 +1,237 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Support.c

+

+Abstract:

+

+Revision History:

+

+--*/

+#include "EfiLdr.h"

+

+EFI_STATUS

+EfiAddMemoryDescriptor(

+  UINTN                 *NoDesc,

+  EFI_MEMORY_DESCRIPTOR *Desc,

+  EFI_MEMORY_TYPE       Type,

+  EFI_PHYSICAL_ADDRESS  BaseAddress,

+  UINT64                NoPages,

+  UINT64                Attribute

+  )

+{

+  UINTN  NumberOfDesc;

+  UINT64 Temp;

+  UINTN  Index;

+

+  if (NoPages == 0) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // See if the new memory descriptor needs to be carved out of an existing memory descriptor

+  //

+

+  NumberOfDesc = *NoDesc;

+  for (Index = 0; Index < NumberOfDesc; Index++) {

+

+    if (Desc[Index].Type == EfiConventionalMemory) {

+

+      Temp = DivU64x32 ((BaseAddress - Desc[Index].PhysicalStart), EFI_PAGE_SIZE) + NoPages;

+

+      if ((Desc[Index].PhysicalStart < BaseAddress) && (Desc[Index].NumberOfPages >= Temp)) {

+        if (Desc[Index].NumberOfPages > Temp) {

+          Desc[*NoDesc].Type          = EfiConventionalMemory;

+          Desc[*NoDesc].PhysicalStart = BaseAddress + MultU64x32 (NoPages, EFI_PAGE_SIZE);

+          Desc[*NoDesc].NumberOfPages = Desc[Index].NumberOfPages - Temp;

+          Desc[*NoDesc].VirtualStart  = 0;

+          Desc[*NoDesc].Attribute     = Desc[Index].Attribute;

+          *NoDesc = *NoDesc + 1;

+        }

+        Desc[Index].NumberOfPages = Temp - NoPages;

+      }

+

+      if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages == NoPages)) {

+        Desc[Index].Type      = Type;

+        Desc[Index].Attribute = Attribute;

+        return EFI_SUCCESS;

+      }

+

+      if ((Desc[Index].PhysicalStart == BaseAddress) && (Desc[Index].NumberOfPages > NoPages)) {

+        Desc[Index].NumberOfPages -= NoPages;

+        Desc[Index].PhysicalStart += MultU64x32 (NoPages, EFI_PAGE_SIZE);

+      }

+    }

+  }

+

+  //

+  // Add the new memory descriptor

+  //

+

+  Desc[*NoDesc].Type          = Type;

+  Desc[*NoDesc].PhysicalStart = BaseAddress;

+  Desc[*NoDesc].NumberOfPages = NoPages;

+  Desc[*NoDesc].VirtualStart  = 0;

+  Desc[*NoDesc].Attribute     = Attribute;

+  *NoDesc = *NoDesc + 1;

+

+  return EFI_SUCCESS;

+}

+

+UINTN

+FindSpace (

+  UINTN                       NoPages,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor,

+  EFI_MEMORY_TYPE             Type,

+  UINT64                      Attribute

+  )

+{

+  EFI_PHYSICAL_ADDRESS        MaxPhysicalStart;

+  UINT64                      MaxNoPages;

+  UINTN                       Index;

+  EFI_MEMORY_DESCRIPTOR       *CurrentMemoryDescriptor;

+

+  MaxPhysicalStart = 0;

+  MaxNoPages       = 0;

+  CurrentMemoryDescriptor = NULL;

+  for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {

+    if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000) {

+      continue;

+    }

+    if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) && 

+        (EfiMemoryDescriptor[Index].NumberOfPages >= NoPages)) {

+      if (EfiMemoryDescriptor[Index].PhysicalStart > MaxPhysicalStart) {

+        if (EfiMemoryDescriptor[Index].PhysicalStart + LShiftU64(EfiMemoryDescriptor[Index].NumberOfPages, EFI_PAGE_SHIFT) <= 0x100000000ULL) {

+          MaxPhysicalStart = EfiMemoryDescriptor[Index].PhysicalStart;

+          MaxNoPages       = EfiMemoryDescriptor[Index].NumberOfPages;

+          CurrentMemoryDescriptor = &EfiMemoryDescriptor[Index];

+        }

+      }

+    }

+    if ((EfiMemoryDescriptor[Index].Type == EfiReservedMemoryType) ||

+        (EfiMemoryDescriptor[Index].Type >= EfiACPIReclaimMemory) ) {

+      continue;

+    }

+    if ((EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesCode) ||

+        (EfiMemoryDescriptor[Index].Type == EfiRuntimeServicesData)) {

+      break;

+    }

+  }

+ 

+  if (MaxPhysicalStart == 0) {

+    return 0;

+  }

+

+  if (MaxNoPages != NoPages) {

+    CurrentMemoryDescriptor->NumberOfPages = MaxNoPages - NoPages;

+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Type          = Type;

+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].PhysicalStart = MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT);

+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].NumberOfPages = NoPages;

+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].VirtualStart  = 0;

+    EfiMemoryDescriptor[*NumberOfMemoryMapEntries].Attribute     = Attribute;

+    *NumberOfMemoryMapEntries = *NumberOfMemoryMapEntries + 1;

+  } else {

+    CurrentMemoryDescriptor->Type      = Type;

+    CurrentMemoryDescriptor->Attribute = Attribute;

+  }

+

+  return (UINTN)(MaxPhysicalStart + LShiftU64(MaxNoPages - NoPages, EFI_PAGE_SHIFT));

+}

+

+VOID

+GenMemoryMap (

+  UINTN                 *NumberOfMemoryMapEntries,

+  EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor,

+  BIOS_MEMORY_MAP       *BiosMemoryMap

+  )

+{

+  UINT64                BaseAddress;

+  UINT64                Length;

+  EFI_MEMORY_TYPE       Type;

+  UINTN                 Index;

+  UINTN                 Attr;

+  UINT64                Ceiling;

+

+  Ceiling = 0xFFFFFFFF;

+  for (Index = 0; Index < BiosMemoryMap->MemoryMapSize / sizeof(BIOS_MEMORY_MAP_ENTRY); Index++) {

+

+    switch (BiosMemoryMap->MemoryMapEntry[Index].Type) { 

+    case (INT15_E820_AddressRangeMemory):

+      Type = EfiConventionalMemory;

+      Attr = EFI_MEMORY_WB;

+      break;

+    case (INT15_E820_AddressRangeReserved):

+      Type = EfiReservedMemoryType;

+      Attr = EFI_MEMORY_UC;

+      break;

+    case (INT15_E820_AddressRangeACPI):

+      Type = EfiACPIReclaimMemory;

+      Attr = EFI_MEMORY_WB;

+      break;

+    case (INT15_E820_AddressRangeNVS):

+      Type = EfiACPIMemoryNVS;

+      Attr = EFI_MEMORY_UC;

+      break;

+    default:

+      // We should not get here, according to ACPI 2.0 Spec.

+      // BIOS behaviour of the Int15h, E820h

+      Type = EfiReservedMemoryType;

+      Attr = EFI_MEMORY_UC;

+      break;

+    }

+    if (Type == EfiConventionalMemory) {

+      BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;

+      Length      = BiosMemoryMap->MemoryMapEntry[Index].Length;

+      if (BaseAddress & EFI_PAGE_MASK) {

+        Length      = Length + (BaseAddress & EFI_PAGE_MASK) - EFI_PAGE_SIZE;

+        BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);

+      }

+    } else {

+      BaseAddress = BiosMemoryMap->MemoryMapEntry[Index].BaseAddress;

+      Length      = BiosMemoryMap->MemoryMapEntry[Index].Length + (BaseAddress & EFI_PAGE_MASK);

+      BaseAddress = LShiftU64 (RShiftU64 (BaseAddress, EFI_PAGE_SHIFT), EFI_PAGE_SHIFT);

+      if (Length & EFI_PAGE_MASK) {

+        Length = LShiftU64 (RShiftU64 (Length, EFI_PAGE_SHIFT) + 1, EFI_PAGE_SHIFT);

+      }

+      //

+      // Update Memory Ceiling

+      //

+      if ((BaseAddress >= 0x100000) && (BaseAddress < 0x100000000ULL)) {

+        if (Ceiling > BaseAddress) {

+          Ceiling = BaseAddress;

+        }

+      }

+    }

+    EfiAddMemoryDescriptor (

+      NumberOfMemoryMapEntries,

+      EfiMemoryDescriptor,

+      Type,

+      (EFI_PHYSICAL_ADDRESS)BaseAddress,

+      RShiftU64 (Length, EFI_PAGE_SHIFT),

+      Attr

+      );

+  }

+

+  //

+  // Update MemoryMap according to Ceiling

+  //

+  for (Index = 0; Index < *NumberOfMemoryMapEntries; Index++) {

+    if ((EfiMemoryDescriptor[Index].Type == EfiConventionalMemory) &&

+        (EfiMemoryDescriptor[Index].PhysicalStart > 0x100000) && 

+        (EfiMemoryDescriptor[Index].PhysicalStart < 0x100000000ULL)) {

+      if (EfiMemoryDescriptor[Index].PhysicalStart >= Ceiling) {

+        EfiMemoryDescriptor[Index].Type = EfiReservedMemoryType;

+      }

+    }

+  }

+}

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.h
new file mode 100644
index 0000000..6c5789a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/Support.h
@@ -0,0 +1,50 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  Support.h

+

+Abstract:

+

+Revision History:

+

+--*/

+

+#ifndef _EFILDR_SUPPORT_H_

+#define _EFILDR_SUPPORT_H_

+

+EFI_STATUS

+EfiAddMemoryDescriptor(

+  UINTN                 *NoDesc,

+  EFI_MEMORY_DESCRIPTOR *Desc,

+  EFI_MEMORY_TYPE       Type,

+  EFI_PHYSICAL_ADDRESS  BaseAddress,

+  UINT64                NoPages,

+  UINT64                Attribute

+  );

+

+UINTN

+FindSpace(

+  UINTN                       NoPages,

+  IN UINTN                    *NumberOfMemoryMapEntries,

+  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor,

+  EFI_MEMORY_TYPE             Type,

+  UINT64                      Attribute

+  );

+

+VOID

+GenMemoryMap (

+  UINTN                 *NumberOfMemoryMapEntries,

+  EFI_MEMORY_DESCRIPTOR *EfiMemoryDescriptor,

+  BIOS_MEMORY_MAP       *BiosMemoryMap

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.c
new file mode 100644
index 0000000..6fed7a1
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.c
@@ -0,0 +1,990 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  Decompress.c

+

+Abstract:

+

+  Decompressor. Algorithm Ported from OPSD code (Decomp.asm)

+  

+--*/

+#include <TianoDecompress.h>

+//

+// Decompression algorithm begins here

+//

+#define BITBUFSIZ 32

+#define MAXMATCH  256

+#define THRESHOLD 3

+#define CODE_BIT  16

+#define BAD_TABLE - 1

+

+//

+// C: Char&Len Set; P: Position Set; T: exTra Set

+//

+#define NC      (0xff + MAXMATCH + 2 - THRESHOLD)

+#define CBIT    9

+#define MAXPBIT 5

+#define TBIT    5

+#define MAXNP   ((1U << MAXPBIT) - 1)

+#define NT      (CODE_BIT + 3)

+#if NT > MAXNP

+#define NPT NT

+#else

+#define NPT MAXNP

+#endif

+

+typedef struct {

+  UINT8   *mSrcBase;  // Starting address of compressed data

+  UINT8   *mDstBase;  // Starting address of decompressed data

+  UINT32  mOutBuf;

+  UINT32  mInBuf;

+

+  UINT16  mBitCount;

+  UINT32  mBitBuf;

+  UINT32  mSubBitBuf;

+  UINT16  mBlockSize;

+  UINT32  mCompSize;

+  UINT32  mOrigSize;

+

+  UINT16  mBadTableFlag;

+

+  UINT16  mLeft[2 * NC - 1];

+  UINT16  mRight[2 * NC - 1];

+  UINT8   mCLen[NC];

+  UINT8   mPTLen[NPT];

+  UINT16  mCTable[4096];

+  UINT16  mPTTable[256];

+

+  //

+  // The length of the field 'Position Set Code Length Array Size' in Block Header.

+  // For EFI 1.1 de/compression algorithm, mPBit = 4

+  // For Tiano de/compression algorithm, mPBit = 5

+  //

+  UINT8   mPBit;

+} SCRATCH_DATA;

+

+VOID

+FillBuf (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfBits

+  )

+/*++

+

+Routine Description:

+

+  Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.

+

+Arguments:

+

+  Sd        - The global scratch data

+  NumOfBits  - The number of bits to shift and read.

+

+Returns: (VOID)

+

+--*/

+{

+  Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);

+

+  while (NumOfBits > Sd->mBitCount) {

+

+    Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));

+

+    if (Sd->mCompSize > 0) {

+      //

+      // Get 1 byte into SubBitBuf

+      //

+      Sd->mCompSize--;

+      Sd->mSubBitBuf  = 0;

+      Sd->mSubBitBuf  = Sd->mSrcBase[Sd->mInBuf++];

+      Sd->mBitCount   = 8;

+

+    } else {

+      //

+      // No more bits from the source, just pad zero bit.

+      //

+      Sd->mSubBitBuf  = 0;

+      Sd->mBitCount   = 8;

+

+    }

+  }

+

+  Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);

+  Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;

+}

+

+UINT32

+GetBits (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfBits

+  )

+/*++

+

+Routine Description:

+

+  Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent 

+  NumOfBits of bits from source. Returns NumOfBits of bits that are 

+  popped out.

+

+Arguments:

+

+  Sd            - The global scratch data.

+  NumOfBits     - The number of bits to pop and read.

+

+Returns:

+

+  The bits that are popped out.

+

+--*/

+{

+  UINT32  OutBits;

+

+  OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));

+

+  FillBuf (Sd, NumOfBits);

+

+  return OutBits;

+}

+

+UINT16

+MakeTable (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        NumOfChar,

+  IN  UINT8         *BitLen,

+  IN  UINT16        TableBits,

+  OUT UINT16        *Table

+  )

+/*++

+

+Routine Description:

+

+  Creates Huffman Code mapping table according to code length array.

+

+Arguments:

+

+  Sd        - The global scratch data

+  NumOfChar - Number of symbols in the symbol set

+  BitLen    - Code length array

+  TableBits - The width of the mapping table

+  Table     - The table

+  

+Returns:

+  

+  0         - OK.

+  BAD_TABLE - The table is corrupted.

+

+--*/

+{

+  UINT16  Count[17];

+  UINT16  Weight[17];

+  UINT16  Start[18];

+  UINT16  *Pointer;

+  UINT16  Index3;

+  volatile UINT16  Index;

+  UINT16  Len;

+  UINT16  Char;

+  UINT16  JuBits;

+  UINT16  Avail;

+  UINT16  NextCode;

+  UINT16  Mask;

+  UINT16  WordOfStart;

+  UINT16  WordOfCount;

+

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

+    Count[Index] = 0;

+  }  

+

+  for (Index = 0; Index < NumOfChar; Index++) {

+    Count[BitLen[Index]]++;

+  }

+

+  Start[1] = 0;

+

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

+    WordOfStart = Start[Index];

+    WordOfCount = Count[Index];

+    Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index)));

+  }

+

+  if (Start[17] != 0) {

+    /*(1U << 16)*/

+    return (UINT16) BAD_TABLE;

+  }

+

+  JuBits = (UINT16) (16 - TableBits);

+

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

+    Start[Index] >>= JuBits;

+    Weight[Index] = (UINT16) (1U << (TableBits - Index));

+  }

+

+  while (Index <= 16) {

+    Weight[Index] = (UINT16) (1U << (16 - Index));

+    Index++;

+  }

+

+  Index = (UINT16) (Start[TableBits + 1] >> JuBits);

+

+  if (Index != 0) {

+    Index3 = (UINT16) (1U << TableBits);

+    while (Index != Index3) {

+      Table[Index++] = 0;

+    }

+  }

+

+  Avail = NumOfChar;

+  Mask  = (UINT16) (1U << (15 - TableBits));

+

+  for (Char = 0; Char < NumOfChar; Char++) {

+

+    Len = BitLen[Char];

+    if (Len == 0) {

+      continue;

+    }

+

+    NextCode = (UINT16) (Start[Len] + Weight[Len]);

+

+    if (Len <= TableBits) {

+

+      for (Index = Start[Len]; Index < NextCode; Index++) {

+        Table[Index] = Char;

+      }

+

+    } else {

+

+      Index3  = Start[Len];

+      Pointer = &Table[Index3 >> JuBits];

+      Index   = (UINT16) (Len - TableBits);

+

+      while (Index != 0) {

+        if (*Pointer == 0) {

+          Sd->mRight[Avail]                     = Sd->mLeft[Avail] = 0;

+          *Pointer = Avail++;

+        }

+

+        if (Index3 & Mask) {

+          Pointer = &Sd->mRight[*Pointer];

+        } else {

+          Pointer = &Sd->mLeft[*Pointer];

+        }

+

+        Index3 <<= 1;

+        Index--;

+      }

+

+      *Pointer = Char;

+

+    }

+

+    Start[Len] = NextCode;

+  }

+  //

+  // Succeeds

+  //

+  return 0;

+}

+

+UINT32

+DecodeP (

+  IN  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decodes a position value.

+

+Arguments:

+

+  Sd      - the global scratch data

+

+Returns:

+

+  The position value decoded.

+

+--*/

+{

+  UINT16  Val;

+  UINT32  Mask;

+  UINT32  Pos;

+

+  Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];

+

+  if (Val >= MAXNP) {

+    Mask = 1U << (BITBUFSIZ - 1 - 8);

+

+    do {

+

+      if (Sd->mBitBuf & Mask) {

+        Val = Sd->mRight[Val];

+      } else {

+        Val = Sd->mLeft[Val];

+      }

+

+      Mask >>= 1;

+    } while (Val >= MAXNP);

+  }

+  //

+  // Advance what we have read

+  //

+  FillBuf (Sd, Sd->mPTLen[Val]);

+

+  Pos = Val;

+  if (Val > 1) {

+    Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));

+  }

+

+  return Pos;

+}

+

+UINT16

+ReadPTLen (

+  IN  SCRATCH_DATA  *Sd,

+  IN  UINT16        nn,

+  IN  UINT16        nbit,

+  IN  UINT16        Special

+  )

+/*++

+

+Routine Description:

+

+  Reads code lengths for the Extra Set or the Position Set

+

+Arguments:

+

+  Sd        - The global scratch data

+  nn        - Number of symbols

+  nbit      - Number of bits needed to represent nn

+  Special   - The special symbol that needs to be taken care of 

+

+Returns:

+

+  0         - OK.

+  BAD_TABLE - Table is corrupted.

+

+--*/

+{

+  UINT16  Number;

+  UINT16  CharC;

+  volatile UINT16  Index;

+  UINT32  Mask;

+

+  Number = (UINT16) GetBits (Sd, nbit);

+

+  if (Number == 0) {

+    CharC = (UINT16) GetBits (Sd, nbit);

+

+    for (Index = 0; Index < 256; Index++) {

+      Sd->mPTTable[Index] = CharC;

+    }

+

+    for (Index = 0; Index < nn; Index++) {

+      Sd->mPTLen[Index] = 0;

+    }

+

+    return 0;

+  }

+

+  Index = 0;

+

+  while (Index < Number) {

+

+    CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));

+

+    if (CharC == 7) {

+      Mask = 1U << (BITBUFSIZ - 1 - 3);

+      while (Mask & Sd->mBitBuf) {

+        Mask >>= 1;

+        CharC += 1;

+      }

+    }

+

+    FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));

+

+    Sd->mPTLen[Index++] = (UINT8) CharC;

+

+    if (Index == Special) {

+      CharC = (UINT16) GetBits (Sd, 2);

+      while ((INT16) (--CharC) >= 0) {

+        Sd->mPTLen[Index++] = 0;

+      }

+    }

+  }

+

+  while (Index < nn) {

+    Sd->mPTLen[Index++] = 0;

+  }

+

+  return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);

+}

+

+VOID

+ReadCLen (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Reads code lengths for Char&Len Set.

+

+Arguments:

+

+  Sd    - the global scratch data

+

+Returns: (VOID)

+

+--*/

+{

+  UINT16  Number;

+  UINT16  CharC;

+  volatile UINT16  Index;

+  UINT32  Mask;

+

+  Number = (UINT16) GetBits (Sd, CBIT);

+

+  if (Number == 0) {

+    CharC = (UINT16) GetBits (Sd, CBIT);

+

+    for (Index = 0; Index < NC; Index++) {

+      Sd->mCLen[Index] = 0;

+    }

+

+    for (Index = 0; Index < 4096; Index++) {

+      Sd->mCTable[Index] = CharC;

+    }

+

+    return ;

+  }

+

+  Index = 0;

+  while (Index < Number) {

+

+    CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];

+    if (CharC >= NT) {

+      Mask = 1U << (BITBUFSIZ - 1 - 8);

+

+      do {

+

+        if (Mask & Sd->mBitBuf) {

+          CharC = Sd->mRight[CharC];

+        } else {

+          CharC = Sd->mLeft[CharC];

+        }

+

+        Mask >>= 1;

+

+      } while (CharC >= NT);

+    }

+    //

+    // Advance what we have read

+    //

+    FillBuf (Sd, Sd->mPTLen[CharC]);

+

+    if (CharC <= 2) {

+

+      if (CharC == 0) {

+        CharC = 1;

+      } else if (CharC == 1) {

+        CharC = (UINT16) (GetBits (Sd, 4) + 3);

+      } else if (CharC == 2) {

+        CharC = (UINT16) (GetBits (Sd, CBIT) + 20);

+      }

+

+      while ((INT16) (--CharC) >= 0) {

+        Sd->mCLen[Index++] = 0;

+      }

+

+    } else {

+

+      Sd->mCLen[Index++] = (UINT8) (CharC - 2);

+

+    }

+  }

+

+  while (Index < NC) {

+    Sd->mCLen[Index++] = 0;

+  }

+

+  MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);

+

+  return ;

+}

+

+UINT16

+DecodeC (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decode a character/length value.

+

+Arguments:

+

+  Sd    - The global scratch data.

+

+Returns:

+

+  The value decoded.

+

+--*/

+{

+  UINT16  Index2;

+  UINT32  Mask;

+

+  if (Sd->mBlockSize == 0) {

+    //

+    // Starting a new block

+    //

+    Sd->mBlockSize    = (UINT16) GetBits (Sd, 16);

+    Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);

+    if (Sd->mBadTableFlag != 0) {

+      return 0;

+    }

+

+    ReadCLen (Sd);

+

+    Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1));

+    if (Sd->mBadTableFlag != 0) {

+      return 0;

+    }

+  }

+

+  Sd->mBlockSize--;

+  Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];

+

+  if (Index2 >= NC) {

+    Mask = 1U << (BITBUFSIZ - 1 - 12);

+

+    do {

+      if (Sd->mBitBuf & Mask) {

+        Index2 = Sd->mRight[Index2];

+      } else {

+        Index2 = Sd->mLeft[Index2];

+      }

+

+      Mask >>= 1;

+    } while (Index2 >= NC);

+  }

+  //

+  // Advance what we have read

+  //

+  FillBuf (Sd, Sd->mCLen[Index2]);

+

+  return Index2;

+}

+

+VOID

+Decode (

+  SCRATCH_DATA  *Sd

+  )

+/*++

+

+Routine Description:

+

+  Decode the source data and put the resulting data into the destination buffer.

+

+Arguments:

+

+  Sd            - The global scratch data

+

+Returns: (VOID)

+

+ --*/

+{

+  UINT16  BytesRemain;

+  UINT32  DataIdx;

+  UINT16  CharC;

+

+  BytesRemain = (UINT16) (-1);

+

+  DataIdx     = 0;

+

+  for (;;) {

+    CharC = DecodeC (Sd);

+    if (Sd->mBadTableFlag != 0) {

+      goto Done ;

+    }

+

+    if (CharC < 256) {

+      //

+      // Process an Original character

+      //

+      if (Sd->mOutBuf >= Sd->mOrigSize) {

+        goto Done ;

+      } else {

+        Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;

+      }

+

+    } else {

+      //

+      // Process a Pointer

+      //

+      CharC       = (UINT16) (CharC - (BIT8 - THRESHOLD));

+

+      BytesRemain = CharC;

+

+      DataIdx     = Sd->mOutBuf - DecodeP (Sd) - 1;

+

+      BytesRemain--;

+      while ((INT16) (BytesRemain) >= 0) {

+        Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];

+        if (Sd->mOutBuf >= Sd->mOrigSize) {

+          goto Done ;

+        }

+

+        BytesRemain--;

+      }

+    }

+  }

+

+Done:

+  return ;

+}

+

+EFI_STATUS

+GetInfo (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  OUT     UINT32  *DstSize,

+  OUT     UINT32  *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  UINT8 *Src;

+

+  *ScratchSize  = sizeof (SCRATCH_DATA);

+

+  Src           = Source;

+  if (SrcSize < 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+Decompress (

+  IN      VOID    *Source,

+  IN      UINT32  SrcSize,

+  IN OUT  VOID    *Destination,

+  IN      UINT32  DstSize,

+  IN OUT  VOID    *Scratch,

+  IN      UINT32  ScratchSize,

+  IN      UINT8   Version

+  )

+/*++

+

+Routine Description:

+

+  The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+  Version     - The version of de/compression algorithm.

+                Version 1 for EFI 1.1 de/compression algorithm.

+                Version 2 for Tiano de/compression algorithm.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  UINT32        CompSize;

+  UINT32        OrigSize;

+  EFI_STATUS    Status;

+  SCRATCH_DATA  *Sd;

+  UINT8         *Src;

+  UINT8         *Dst;

+  volatile UINT32  Index;

+  

+  Status  = EFI_SUCCESS;

+  Src     = Source;

+  Dst     = Destination;

+

+  if (ScratchSize < sizeof (SCRATCH_DATA)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Sd = (SCRATCH_DATA *) Scratch;

+

+  if (SrcSize < 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CompSize  = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);

+  OrigSize  = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);

+

+  //

+  // If compressed file size is 0, return

+  //

+  if (OrigSize == 0) {

+    return Status;

+  }

+

+  if (SrcSize < CompSize + 8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (DstSize != OrigSize) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Src = Src + 8;

+

+  for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {

+    ((UINT8 *) Sd)[Index] = 0;

+  }

+  

+  //

+  // The length of the field 'Position Set Code Length Array Size' in Block Header.

+  // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4

+  // For Tiano de/compression algorithm(Version 2), mPBit = 5

+  //

+  switch (Version) {

+  case 1:

+    Sd->mPBit = 4;

+    break;

+

+  case 2:

+    Sd->mPBit = 5;

+    break;

+

+  default:

+    //

+    // Currently, only have 2 versions

+    //

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Sd->mSrcBase  = Src;

+  Sd->mDstBase  = Dst;

+  Sd->mCompSize = CompSize;

+  Sd->mOrigSize = OrigSize;

+

+  //

+  // Fill the first BITBUFSIZ bits

+  //

+  FillBuf (Sd, BITBUFSIZ);

+

+  //

+  // Decompress it

+  //

+  Decode (Sd);

+

+  if (Sd->mBadTableFlag != 0) {

+    //

+    // Something wrong with the source

+    //

+    Status = EFI_INVALID_PARAMETER;

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+EfiGetInfo (

+  IN      VOID                    *Source,

+  IN      UINT32                  SrcSize,

+  OUT     UINT32                  *DstSize,

+  OUT     UINT32                  *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that  of EFI_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  return GetInfo (

+          Source,

+          SrcSize,

+          DstSize,

+          ScratchSize

+          );

+}

+

+EFI_STATUS

+EFIAPI

+EfiDecompress (

+  IN      VOID                    *Source,

+  IN      UINT32                  SrcSize,

+  IN OUT  VOID                    *Destination,

+  IN      UINT32                  DstSize,

+  IN OUT  VOID                    *Scratch,

+  IN      UINT32                  ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  //

+  // For EFI 1.1 de/compression algorithm, the version is 1.

+  //

+  return Decompress (

+          Source,

+          SrcSize,

+          Destination,

+          DstSize,

+          Scratch,

+          ScratchSize,

+          1

+          );

+}

+

+EFI_STATUS

+EFIAPI

+TianoGetInfo (

+  IN      VOID                          *Source,

+  IN      UINT32                        SrcSize,

+  OUT     UINT32                        *DstSize,

+  OUT     UINT32                        *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  return GetInfo (

+          Source,

+          SrcSize,

+          DstSize,

+          ScratchSize

+          );

+}

+

+EFI_STATUS

+EFIAPI

+TianoDecompress (

+  IN      VOID                          *Source,

+  IN      UINT32                        SrcSize,

+  IN OUT  VOID                          *Destination,

+  IN      UINT32                        DstSize,

+  IN OUT  VOID                          *Scratch,

+  IN      UINT32                        ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that  of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+{

+  //

+  // For Tiano de/compression algorithm, the version is 2.

+  //

+  return Decompress (

+          Source,

+          SrcSize,

+          Destination,

+          DstSize,

+          Scratch,

+          ScratchSize,

+          2

+          );

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.h b/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.h
new file mode 100644
index 0000000..0d85b7b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/TianoDecompress.h
@@ -0,0 +1,90 @@
+/** @file

+  Internal include file for Base UEFI Decompress Libary.

+

+  Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+  Module Name:  BaseUefiCustomDecompressLibInternals.h

+

+**/

+

+#ifndef __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__

+#define __BASE_UEFI_TIANO_CUSTOM_DECOMPRESS_LIB_INTERNALS_H__

+

+#include <PiPei.h>

+

+#include <Library/UefiDecompressLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+

+EFI_STATUS

+EFIAPI

+TianoGetInfo (

+  IN      VOID                          *Source,

+  IN      UINT32                        SrcSize,

+  OUT     UINT32                        *DstSize,

+  OUT     UINT32                        *ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  DstSize     - The size of destination buffer.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - The size of destination buffer and the size of scratch buffer are successull retrieved.

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+TianoDecompress (

+  IN      VOID                          *Source,

+  IN      UINT32                        SrcSize,

+  IN OUT  VOID                          *Destination,

+  IN      UINT32                        DstSize,

+  IN OUT  VOID                          *Scratch,

+  IN      UINT32                        ScratchSize

+  )

+/*++

+

+Routine Description:

+

+  The implementation is same as that  of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress().

+

+Arguments:

+

+  This        - The protocol instance pointer

+  Source      - The source buffer containing the compressed data.

+  SrcSize     - The size of source buffer

+  Destination - The destination buffer to store the decompressed data

+  DstSize     - The size of destination buffer.

+  Scratch     - The buffer used internally by the decompress routine. This  buffer is needed to store intermediate data.

+  ScratchSize - The size of scratch buffer.

+

+Returns:

+

+  EFI_SUCCESS           - Decompression is successfull

+  EFI_INVALID_PARAMETER - The source data is corrupted

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/EfiLdr/efildr.c b/uefi/linaro-edk2/DuetPkg/EfiLdr/efildr.c
new file mode 100644
index 0000000..2b40aca
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/EfiLdr/efildr.c
@@ -0,0 +1,28 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  EfiLdr.c

+

+Abstract:

+

+Revision History:

+

+--*/

+

+//

+// BUGBUG, include all C files

+//

+#include "EfiLoader.c"

+#include "PeLoader.c"

+#include "Support.c"

+#include "Debug.c"

+

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.c b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.c
new file mode 100644
index 0000000..5e72f9f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.c
@@ -0,0 +1,1960 @@
+/*++

+

+Caution: This file is used for Duet platform only, do not use them in real platform.

+All variable code, variable metadata, and variable data used by Duet platform are on 

+disk. They can be changed by user. BIOS is not able to protoect those.

+Duet trusts all meta data from disk. If variable code, variable metadata and variable

+data is modified in inproper way, the behavior is undefined.

+

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

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+  FSVariable.c

+

+Abstract:

+

+  Provide support functions for variable services.

+

+--*/

+

+#include "FSVariable.h"

+

+VARIABLE_STORE_HEADER mStoreHeaderTemplate = {

+  VARIABLE_STORE_SIGNATURE,

+  VOLATILE_VARIABLE_STORE_SIZE,

+  VARIABLE_STORE_FORMATTED,

+  VARIABLE_STORE_HEALTHY,

+  0,

+  0

+};

+

+//

+// Don't use module globals after the SetVirtualAddress map is signaled

+//

+VARIABLE_GLOBAL  *mGlobal;

+

+/**

+  Update the variable region with Variable information. These are the same 

+  arguments as the EFI Variable services.

+

+  @param[in] VariableName       Name of variable

+

+  @param[in] VendorGuid         Guid of variable

+

+  @param[in] Data               Variable data

+

+  @param[in] DataSize           Size of data. 0 means delete

+

+  @param[in] Attributes         Attribues of the variable

+

+  @param[in] Variable           The variable information which is used to keep track of variable usage.

+

+  @retval EFI_SUCCESS           The update operation is success.

+

+  @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.

+

+**/

+EFI_STATUS

+EFIAPI

+UpdateVariable (

+  IN      CHAR16                 *VariableName,

+  IN      EFI_GUID               *VendorGuid,

+  IN      VOID                   *Data,

+  IN      UINTN                  DataSize,

+  IN      UINT32                 Attributes OPTIONAL,

+  IN      VARIABLE_POINTER_TRACK *Variable

+  );

+

+VOID

+EFIAPI

+OnVirtualAddressChangeFsv (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  );

+

+VOID

+EFIAPI

+OnSimpleFileSystemInstall (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  );

+

+BOOLEAN

+IsValidVariableHeader (

+  IN  VARIABLE_HEADER   *Variable

+  )

+/*++

+

+Routine Description:

+

+  This code checks if variable header is valid or not.

+

+Arguments:

+  Variable        Pointer to the Variable Header.

+

+Returns:

+  TRUE            Variable header is valid.

+  FALSE           Variable header is not valid.

+

+--*/

+{

+  if (Variable == NULL || Variable->StartId != VARIABLE_DATA) {

+    return FALSE;

+  }

+

+  return TRUE;

+}

+

+VARIABLE_STORE_STATUS

+GetVariableStoreStatus (

+  IN VARIABLE_STORE_HEADER *VarStoreHeader

+  )

+/*++

+

+Routine Description:

+

+  This code gets the current status of Variable Store.

+

+Arguments:

+

+  VarStoreHeader  Pointer to the Variable Store Header.

+

+Returns:

+

+  EfiRaw        Variable store status is raw

+  EfiValid      Variable store status is valid

+  EfiInvalid    Variable store status is invalid

+

+--*/

+{

+  if (CompareGuid (&VarStoreHeader->Signature, &mStoreHeaderTemplate.Signature) &&

+      (VarStoreHeader->Format == mStoreHeaderTemplate.Format) &&

+      (VarStoreHeader->State == mStoreHeaderTemplate.State)

+     ) {

+    return EfiValid;

+  } else if (((UINT32 *)(&VarStoreHeader->Signature))[0] == VAR_DEFAULT_VALUE_32 &&

+             ((UINT32 *)(&VarStoreHeader->Signature))[1] == VAR_DEFAULT_VALUE_32 &&

+             ((UINT32 *)(&VarStoreHeader->Signature))[2] == VAR_DEFAULT_VALUE_32 &&

+             ((UINT32 *)(&VarStoreHeader->Signature))[3] == VAR_DEFAULT_VALUE_32 &&

+             VarStoreHeader->Size == VAR_DEFAULT_VALUE_32 &&

+             VarStoreHeader->Format == VAR_DEFAULT_VALUE &&

+             VarStoreHeader->State == VAR_DEFAULT_VALUE

+          ) {

+

+    return EfiRaw;

+  } else {

+    return EfiInvalid;

+  }

+}

+

+UINT8 *

+GetVariableDataPtr (

+  IN  VARIABLE_HEADER   *Variable

+  )

+/*++

+

+Routine Description:

+

+  This code gets the pointer to the variable data.

+

+Arguments:

+

+  Variable            Pointer to the Variable Header.

+

+Returns:

+

+  UINT8*              Pointer to Variable Data

+

+--*/

+{

+  //

+  // Be careful about pad size for alignment

+  //

+  return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize));

+}

+

+VARIABLE_HEADER *

+GetNextVariablePtr (

+  IN  VARIABLE_HEADER   *Variable

+  )

+/*++

+

+Routine Description:

+

+  This code gets the pointer to the next variable header.

+

+Arguments:

+

+  Variable              Pointer to the Variable Header.

+

+Returns:

+

+  VARIABLE_HEADER*      Pointer to next variable header.

+

+--*/

+{

+  if (!IsValidVariableHeader (Variable)) {

+    return NULL;

+  }

+  //

+  // Be careful about pad size for alignment

+  //

+  return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize));

+}

+

+VARIABLE_HEADER *

+GetEndPointer (

+  IN VARIABLE_STORE_HEADER       *VarStoreHeader

+  )

+/*++

+

+Routine Description:

+

+  This code gets the pointer to the last variable memory pointer byte

+

+Arguments:

+

+  VarStoreHeader        Pointer to the Variable Store Header.

+

+Returns:

+

+  VARIABLE_HEADER*      Pointer to last unavailable Variable Header

+

+--*/

+{

+  //

+  // The end of variable store

+  //

+  return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size);

+}

+

+BOOLEAN

+ExistNewerVariable (

+  IN  VARIABLE_HEADER         *Variable

+  )

+/*++

+

+Routine Description:

+

+  Check if exist newer variable when doing reclaim

+

+Arguments:

+

+  Variable                    Pointer to start position

+

+Returns:

+

+  TRUE - Exists another variable, which is newer than the current one

+  FALSE  - Doesn't exist another vairable which is newer than the current one

+

+--*/

+{

+  VARIABLE_HEADER       *NextVariable;

+  CHAR16                *VariableName;

+  EFI_GUID              *VendorGuid;

+  

+  VendorGuid   = &Variable->VendorGuid;

+  VariableName = GET_VARIABLE_NAME_PTR(Variable);

+  

+  NextVariable = GetNextVariablePtr (Variable);

+  while (IsValidVariableHeader (NextVariable)) {

+    if ((NextVariable->State == VAR_ADDED) || (NextVariable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {

+      //

+      // If match Guid and Name

+      //

+      if (CompareGuid (VendorGuid, &NextVariable->VendorGuid)) {

+         if (CompareMem (VariableName, GET_VARIABLE_NAME_PTR (NextVariable), StrSize (VariableName)) == 0) {

+           return TRUE;

+         }

+       }

+    }

+    NextVariable = GetNextVariablePtr (NextVariable);

+  }

+  return FALSE;

+}

+

+EFI_STATUS

+Reclaim (

+  IN  VARIABLE_STORAGE_TYPE StorageType,

+  IN  VARIABLE_HEADER       *CurrentVariable OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  Variable store garbage collection and reclaim operation

+

+Arguments:

+

+  IsVolatile                  The variable store is volatile or not,

+                              if it is non-volatile, need FTW

+  CurrentVairable             If it is not NULL, it means not to process

+                              current variable for Reclaim.

+

+Returns:

+

+  EFI STATUS

+

+--*/

+{

+  VARIABLE_HEADER       *Variable;

+  VARIABLE_HEADER       *NextVariable;

+  VARIABLE_STORE_HEADER *VariableStoreHeader;

+  UINT8                 *ValidBuffer;

+  UINTN                 ValidBufferSize;

+  UINTN                 VariableSize;

+  UINT8                 *CurrPtr;

+  EFI_STATUS            Status;

+

+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType];

+

+  //

+  // Start Pointers for the variable.

+  //

+  Variable        = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

+

+  //

+  // recaluate the total size of Common/HwErr type variables in non-volatile area.

+  //

+  if (!StorageType) {

+    mGlobal->CommonVariableTotalSize = 0;

+    mGlobal->HwErrVariableTotalSize  = 0;

+  }

+  //

+  // To make the reclaim, here we just allocate a memory that equal to the original memory

+  //

+  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER) + VariableStoreHeader->Size;

+

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  ValidBufferSize,

+                  (VOID**) &ValidBuffer

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  CurrPtr = ValidBuffer;

+

+  //

+  // Copy variable store header

+  //

+  CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER));

+  CurrPtr += sizeof (VARIABLE_STORE_HEADER);

+

+  //

+  // Start Pointers for the variable.

+  //

+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

+

+  

+  ValidBufferSize = sizeof (VARIABLE_STORE_HEADER);

+  while (IsValidVariableHeader (Variable)) {

+    NextVariable = GetNextVariablePtr (Variable);

+    //

+    // State VAR_ADDED or VAR_IN_DELETED_TRANSITION are to kept,

+    // The CurrentVariable, is also saved, as SetVariable may fail due to lack of space

+    //

+    if (Variable->State == VAR_ADDED) {

+      VariableSize = (UINTN) NextVariable - (UINTN) Variable;

+      CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);

+      ValidBufferSize += VariableSize;

+      CurrPtr += VariableSize;

+      if ((!StorageType) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+        mGlobal->HwErrVariableTotalSize += VariableSize;

+      } else if ((!StorageType) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+        mGlobal->CommonVariableTotalSize += VariableSize;

+      }

+    } else if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {

+      //

+      // As variables that with the same guid and name may exist in NV due to power failure during SetVariable,

+      // we will only save the latest valid one

+      //

+      if (!ExistNewerVariable(Variable)) {

+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;

+        CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize);

+        //

+        // If CurrentVariable == Variable, mark as VAR_IN_DELETED_TRANSITION

+        //

+        if (Variable != CurrentVariable){

+          ((VARIABLE_HEADER *)CurrPtr)->State = VAR_ADDED;

+        }

+        CurrPtr += VariableSize;

+        ValidBufferSize += VariableSize;

+        if ((!StorageType) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+          mGlobal->HwErrVariableTotalSize += VariableSize;

+        } else if ((!StorageType) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+          mGlobal->CommonVariableTotalSize += VariableSize;

+        }

+      }

+    }

+    Variable = NextVariable;

+  }

+

+  mGlobal->LastVariableOffset[StorageType] = ValidBufferSize;

+

+  //

+  // TODO: cannot restore to original state, basic FTW needed

+  //

+  Status = mGlobal->VariableStore[StorageType]->Erase (

+                                                  mGlobal->VariableStore[StorageType]

+                                                  );

+  Status = mGlobal->VariableStore[StorageType]->Write (

+                                                    mGlobal->VariableStore[StorageType],

+                                                    0,

+                                                    ValidBufferSize,

+                                                    ValidBuffer

+                                                    );

+

+  if (EFI_ERROR (Status)) {

+    //

+    // If error, then reset the last variable offset to zero.

+    //

+    mGlobal->LastVariableOffset[StorageType] = 0;

+  };

+

+  gBS->FreePool (ValidBuffer);

+

+  return Status;

+}

+

+EFI_STATUS

+FindVariable (

+  IN  CHAR16                  *VariableName,

+  IN  EFI_GUID                *VendorGuid,

+  OUT VARIABLE_POINTER_TRACK  *PtrTrack

+  )

+/*++

+

+Routine Description:

+

+  This code finds variable in storage blocks (Volatile or Non-Volatile)

+

+Arguments:

+

+  VariableName                Name of the variable to be found

+  VendorGuid                  Vendor GUID to be found.

+  PtrTrack                    Variable Track Pointer structure that contains

+                              Variable Information.

+                              Contains the pointer of Variable header.

+

+Returns:

+

+  EFI_INVALID_PARAMETER       - Invalid parameter

+  EFI_SUCCESS                 - Find the specified variable

+  EFI_NOT_FOUND               - Not found

+

+--*/

+{

+  VARIABLE_HEADER         *Variable;

+  VARIABLE_STORE_HEADER   *VariableStoreHeader;

+  UINTN                   Index;

+  VARIABLE_HEADER         *InDeleteVariable;

+  UINTN                   InDeleteIndex;

+  VARIABLE_HEADER         *InDeleteStartPtr;

+  VARIABLE_HEADER         *InDeleteEndPtr;

+

+  if (VariableName[0] != 0 && VendorGuid == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InDeleteVariable = NULL;

+  InDeleteIndex    = (UINTN)-1;

+  InDeleteStartPtr = NULL;

+  InDeleteEndPtr   = NULL;

+

+  for (Index = 0; Index < MaxType; Index ++) {

+    //

+    // 0: Non-Volatile, 1: Volatile

+    //

+    VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Index];

+

+    //

+    // Start Pointers for the variable.

+    // Actual Data Pointer where data can be written.

+    //

+    Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

+

+    //

+    // Find the variable by walk through non-volatile and volatile variable store

+    //

+    PtrTrack->StartPtr = Variable;

+    PtrTrack->EndPtr   = GetEndPointer (VariableStoreHeader);

+

+    while ((Variable < PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {

+      if (Variable->State == VAR_ADDED) {

+        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {

+          if (VariableName[0] == 0) {

+            PtrTrack->CurrPtr = Variable;

+            PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;

+            return EFI_SUCCESS;

+          } else {

+            if (CompareGuid (VendorGuid, &Variable->VendorGuid)) {

+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), StrSize (VariableName))) {

+                PtrTrack->CurrPtr = Variable;

+                PtrTrack->Type    = (VARIABLE_STORAGE_TYPE) Index;

+                return EFI_SUCCESS;

+              }

+            }

+          }

+        }

+      } else if (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {

+        //

+        // VAR_IN_DELETED_TRANSITION should also be checked.

+        //

+        if (!EfiAtRuntime () || (Variable->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {

+          if (VariableName[0] == 0) {

+            InDeleteVariable = Variable;

+            InDeleteIndex    = Index;

+            InDeleteStartPtr = PtrTrack->StartPtr;

+            InDeleteEndPtr   = PtrTrack->EndPtr;

+          } else {

+            if (CompareGuid (VendorGuid, &Variable->VendorGuid)) {

+              if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable), StrSize (VariableName))) {

+                InDeleteVariable = Variable;

+                InDeleteIndex    = Index;

+                InDeleteStartPtr = PtrTrack->StartPtr;

+                InDeleteEndPtr   = PtrTrack->EndPtr;

+              }

+            }

+          }

+        }

+      }

+

+      Variable = GetNextVariablePtr (Variable);

+    }

+    //

+    // While (...)

+    //

+  }

+  //

+  // for (...)

+  //

+

+  //

+  // if VAR_IN_DELETED_TRANSITION found, and VAR_ADDED not found,

+  // we return it.

+  //

+  if (InDeleteVariable != NULL) {

+    PtrTrack->CurrPtr  = InDeleteVariable;

+    PtrTrack->Type     = (VARIABLE_STORAGE_TYPE) InDeleteIndex;

+    PtrTrack->StartPtr = InDeleteStartPtr;

+    PtrTrack->EndPtr   = InDeleteEndPtr;

+    return EFI_SUCCESS;

+  }

+

+  PtrTrack->CurrPtr = NULL;

+  return EFI_NOT_FOUND;

+}

+

+/**

+  Get index from supported language codes according to language string.

+

+  This code is used to get corresponding index in supported language codes. It can handle

+  RFC4646 and ISO639 language tags.

+  In ISO639 language tags, take 3-characters as a delimitation to find matched string and calculate the index.

+  In RFC4646 language tags, take semicolon as a delimitation to find matched string and calculate the index.

+

+  For example:

+    SupportedLang  = "engfraengfra"

+    Lang           = "eng"

+    Iso639Language = TRUE

+  The return value is "0".

+  Another example:

+    SupportedLang  = "en;fr;en-US;fr-FR"

+    Lang           = "fr-FR"

+    Iso639Language = FALSE

+  The return value is "3".

+

+  @param  SupportedLang               Platform supported language codes.

+  @param  Lang                        Configured language.

+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.

+

+  @retval the index of language in the language codes.

+

+**/

+UINTN

+GetIndexFromSupportedLangCodes(

+  IN  CHAR8            *SupportedLang,

+  IN  CHAR8            *Lang,

+  IN  BOOLEAN          Iso639Language

+  ) 

+{

+  UINTN    Index;

+  UINTN    CompareLength;

+  UINTN    LanguageLength;

+

+  if (Iso639Language) {

+    CompareLength = ISO_639_2_ENTRY_SIZE;

+    for (Index = 0; Index < AsciiStrLen (SupportedLang); Index += CompareLength) {

+      if (AsciiStrnCmp (Lang, SupportedLang + Index, CompareLength) == 0) {

+        //

+        // Successfully find the index of Lang string in SupportedLang string.

+        //

+        Index = Index / CompareLength;

+        return Index;

+      }

+    }

+    ASSERT (FALSE);

+    return 0;

+  } else {

+    //

+    // Compare RFC4646 language code

+    //

+    Index = 0;

+    for (LanguageLength = 0; Lang[LanguageLength] != '\0'; LanguageLength++);

+

+    for (Index = 0; *SupportedLang != '\0'; Index++, SupportedLang += CompareLength) {

+      //

+      // Skip ';' characters in SupportedLang

+      //

+      for (; *SupportedLang != '\0' && *SupportedLang == ';'; SupportedLang++);

+      //

+      // Determine the length of the next language code in SupportedLang

+      //

+      for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);

+      

+      if ((CompareLength == LanguageLength) && 

+          (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {

+        //

+        // Successfully find the index of Lang string in SupportedLang string.

+        //

+        return Index;

+      }

+    }

+    ASSERT (FALSE);

+    return 0;

+  }

+}

+

+/**

+  Get language string from supported language codes according to index.

+

+  This code is used to get corresponding language string in supported language codes. It can handle

+  RFC4646 and ISO639 language tags.

+  In ISO639 language tags, take 3-characters as a delimitation. Find language string according to the index.

+  In RFC4646 language tags, take semicolon as a delimitation. Find language string according to the index.

+

+  For example:

+    SupportedLang  = "engfraengfra"

+    Index          = "1"

+    Iso639Language = TRUE

+  The return value is "fra".

+  Another example:

+    SupportedLang  = "en;fr;en-US;fr-FR"

+    Index          = "1"

+    Iso639Language = FALSE

+  The return value is "fr".

+

+  @param  SupportedLang               Platform supported language codes.

+  @param  Index                       the index in supported language codes.

+  @param  Iso639Language              A bool value to signify if the handler is operated on ISO639 or RFC4646.

+

+  @retval the language string in the language codes.

+

+**/

+CHAR8 *

+GetLangFromSupportedLangCodes (

+  IN  CHAR8            *SupportedLang,

+  IN  UINTN            Index,

+  IN  BOOLEAN          Iso639Language

+)

+{

+  UINTN    SubIndex;

+  UINTN    CompareLength;

+  CHAR8    *Supported;

+

+  SubIndex  = 0;

+  Supported = SupportedLang;

+  if (Iso639Language) {

+    //

+    // according to the index of Lang string in SupportedLang string to get the language.

+    // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

+    // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

+    //

+    CompareLength = ISO_639_2_ENTRY_SIZE;

+    mGlobal->Lang[CompareLength] = '\0';

+    return CopyMem (mGlobal->Lang, SupportedLang + Index * CompareLength, CompareLength);

+

+  } else {

+    while (TRUE) {

+      //

+      // take semicolon as delimitation, sequentially traverse supported language codes.

+      //

+      for (CompareLength = 0; *Supported != ';' && *Supported != '\0'; CompareLength++) {

+        Supported++;

+      }

+      if ((*Supported == '\0') && (SubIndex != Index)) {

+        //

+        // Have completed the traverse, but not find corrsponding string.

+        // This case is not allowed to happen.

+        //

+        ASSERT(FALSE);

+        return NULL;

+      }

+      if (SubIndex == Index) {

+        //

+        // according to the index of Lang string in SupportedLang string to get the language.

+        // As this code will be invoked in RUNTIME, therefore there is not memory allocate/free operation.

+        // In driver entry, it pre-allocates a runtime attribute memory to accommodate this string.

+        //

+        mGlobal->PlatformLang[CompareLength] = '\0';

+        return CopyMem (mGlobal->PlatformLang, Supported - CompareLength, CompareLength);

+      }

+      SubIndex++;

+

+      //

+      // Skip ';' characters in Supported

+      //

+      for (; *Supported != '\0' && *Supported == ';'; Supported++);

+    }

+  }

+}

+

+/**

+  Returns a pointer to an allocated buffer that contains the best matching language 

+  from a set of supported languages.  

+  

+  This function supports both ISO 639-2 and RFC 4646 language codes, but language 

+  code types may not be mixed in a single call to this function. This function

+  supports a variable argument list that allows the caller to pass in a prioritized

+  list of language codes to test against all the language codes in SupportedLanguages.

+

+  If SupportedLanguages is NULL, then ASSERT().

+

+  @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that

+                                  contains a set of language codes in the format 

+                                  specified by Iso639Language.

+  @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be

+                                  in ISO 639-2 format.  If FALSE, then all language

+                                  codes are assumed to be in RFC 4646 language format

+  @param[in]  ...                 A variable argument list that contains pointers to 

+                                  Null-terminated ASCII strings that contain one or more

+                                  language codes in the format specified by Iso639Language.

+                                  The first language code from each of these language

+                                  code lists is used to determine if it is an exact or

+                                  close match to any of the language codes in 

+                                  SupportedLanguages.  Close matches only apply to RFC 4646

+                                  language codes, and the matching algorithm from RFC 4647

+                                  is used to determine if a close match is present.  If 

+                                  an exact or close match is found, then the matching

+                                  language code from SupportedLanguages is returned.  If

+                                  no matches are found, then the next variable argument

+                                  parameter is evaluated.  The variable argument list 

+                                  is terminated by a NULL.

+

+  @retval NULL   The best matching language could not be found in SupportedLanguages.

+  @retval NULL   There are not enough resources available to return the best matching 

+                 language.

+  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching 

+                 language in SupportedLanguages.

+

+**/

+CHAR8 *

+EFIAPI

+VariableGetBestLanguage (

+  IN CONST CHAR8  *SupportedLanguages, 

+  IN BOOLEAN      Iso639Language,

+  ...

+  )

+{

+  VA_LIST      Args;

+  CHAR8        *Language;

+  UINTN        CompareLength;

+  UINTN        LanguageLength;

+  CONST CHAR8  *Supported;

+  CHAR8        *Buffer;

+

+  ASSERT (SupportedLanguages != NULL);

+

+  VA_START (Args, Iso639Language);

+  while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {

+    //

+    // Default to ISO 639-2 mode

+    //

+    CompareLength  = 3;

+    LanguageLength = MIN (3, AsciiStrLen (Language));

+

+    //

+    // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language

+    //

+    if (!Iso639Language) {

+      for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);

+    }

+

+    //

+    // Trim back the length of Language used until it is empty

+    //

+    while (LanguageLength > 0) {

+      //

+      // Loop through all language codes in SupportedLanguages

+      //

+      for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {

+        //

+        // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages

+        //

+        if (!Iso639Language) {

+          //

+          // Skip ';' characters in Supported

+          //

+          for (; *Supported != '\0' && *Supported == ';'; Supported++);

+          //

+          // Determine the length of the next language code in Supported

+          //

+          for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);

+          //

+          // If Language is longer than the Supported, then skip to the next language

+          //

+          if (LanguageLength > CompareLength) {

+            continue;

+          }

+        }

+        //

+        // See if the first LanguageLength characters in Supported match Language

+        //

+        if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {

+          VA_END (Args);

+

+          Buffer = Iso639Language ? mGlobal->Lang : mGlobal->PlatformLang;

+          Buffer[CompareLength] = '\0';

+          return CopyMem (Buffer, Supported, CompareLength);

+        }

+      }

+

+      if (Iso639Language) {

+        //

+        // If ISO 639 mode, then each language can only be tested once

+        //

+        LanguageLength = 0;

+      } else {

+        //

+        // If RFC 4646 mode, then trim Language from the right to the next '-' character 

+        //

+        for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);

+      }

+    }

+  }

+  VA_END (Args);

+

+  //

+  // No matches were found 

+  //

+  return NULL;

+}

+

+/**

+  Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.

+

+  When setting Lang/LangCodes, simultaneously update PlatformLang/PlatformLangCodes.

+

+  According to UEFI spec, PlatformLangCodes/LangCodes are only set once in firmware initialization,

+  and are read-only. Therefore, in variable driver, only store the original value for other use.

+

+  @param[in] VariableName       Name of variable

+

+  @param[in] Data               Variable data

+

+  @param[in] DataSize           Size of data. 0 means delete

+

+**/

+VOID

+AutoUpdateLangVariable(

+  IN  CHAR16             *VariableName,

+  IN  VOID               *Data,

+  IN  UINTN              DataSize

+  )

+{

+  EFI_STATUS             Status;

+  CHAR8                  *BestPlatformLang;

+  CHAR8                  *BestLang;

+  UINTN                  Index;

+  UINT32                 Attributes;

+  VARIABLE_POINTER_TRACK Variable;

+  BOOLEAN                SetLanguageCodes;

+

+  //

+  // Don't do updates for delete operation

+  //

+  if (DataSize == 0) {

+    return;

+  }

+

+  SetLanguageCodes = FALSE;

+

+  if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {

+    //

+    // PlatformLangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, PlatformLangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mGlobal->PlatformLangCodes != NULL) {

+      FreePool (mGlobal->PlatformLangCodes);

+    }

+    mGlobal->PlatformLangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mGlobal->PlatformLangCodes != NULL);

+

+    //

+    // PlatformLang holds a single language from PlatformLangCodes, 

+    // so the size of PlatformLangCodes is enough for the PlatformLang.

+    //

+    if (mGlobal->PlatformLang != NULL) {

+      FreePool (mGlobal->PlatformLang);

+    }

+    mGlobal->PlatformLang = AllocateRuntimePool (DataSize);

+    ASSERT (mGlobal->PlatformLang != NULL);

+

+  } else if (StrCmp (VariableName, L"LangCodes") == 0) {

+    //

+    // LangCodes is a volatile variable, so it can not be updated at runtime.

+    //

+    if (EfiAtRuntime ()) {

+      return;

+    }

+

+    SetLanguageCodes = TRUE;

+

+    //

+    // According to UEFI spec, LangCodes is only set once in firmware initialization, and is read-only

+    // Therefore, in variable driver, only store the original value for other use.

+    //

+    if (mGlobal->LangCodes != NULL) {

+      FreePool (mGlobal->LangCodes);

+    }

+    mGlobal->LangCodes = AllocateRuntimeCopyPool (DataSize, Data);

+    ASSERT (mGlobal->LangCodes != NULL);

+  }

+

+  if (SetLanguageCodes 

+      && (mGlobal->PlatformLangCodes != NULL)

+      && (mGlobal->LangCodes != NULL)) {

+    //

+    // Update Lang if PlatformLang is already set

+    // Update PlatformLang if Lang is already set

+    //

+    Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable);

+    if (!EFI_ERROR (Status)) {

+      //

+      // Update Lang

+      //

+      VariableName = L"PlatformLang";

+      Data         = GetVariableDataPtr (Variable.CurrPtr);

+      DataSize     = Variable.CurrPtr->DataSize;

+    } else {

+      Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Update PlatformLang

+        //

+        VariableName = L"Lang";

+        Data         = GetVariableDataPtr (Variable.CurrPtr);

+        DataSize     = Variable.CurrPtr->DataSize;

+      } else {

+        //

+        // Neither PlatformLang nor Lang is set, directly return

+        //

+        return;

+      }

+    }

+  }

+  

+  //

+  // According to UEFI spec, "Lang" and "PlatformLang" is NV|BS|RT attributions.

+  //

+  Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;

+

+  if (StrCmp (VariableName, L"PlatformLang") == 0) {

+    //

+    // Update Lang when PlatformLangCodes/LangCodes were set.

+    //

+    if ((mGlobal->PlatformLangCodes != NULL) && (mGlobal->LangCodes != NULL)) {

+      //

+      // When setting PlatformLang, firstly get most matched language string from supported language codes.

+      //

+      BestPlatformLang = VariableGetBestLanguage (mGlobal->PlatformLangCodes, FALSE, Data, NULL);

+      if (BestPlatformLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mGlobal->PlatformLangCodes, BestPlatformLang, FALSE);

+

+        //

+        // Get the corresponding ISO639 language tag according to RFC4646 language tag.

+        //

+        BestLang = GetLangFromSupportedLangCodes (mGlobal->LangCodes, Index, TRUE);

+

+        //

+        // Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.

+        //

+        FindVariable(L"Lang", &gEfiGlobalVariableGuid, &Variable);

+

+        Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang, ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);

+

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));

+

+        ASSERT_EFI_ERROR(Status);

+      }

+    }

+

+  } else if (StrCmp (VariableName, L"Lang") == 0) {

+    //

+    // Update PlatformLang when PlatformLangCodes/LangCodes were set.

+    //

+    if ((mGlobal->PlatformLangCodes != NULL) && (mGlobal->LangCodes != NULL)) {

+      //

+      // When setting Lang, firstly get most matched language string from supported language codes.

+      //

+      BestLang = VariableGetBestLanguage (mGlobal->LangCodes, TRUE, Data, NULL);

+      if (BestLang != NULL) {

+        //

+        // Get the corresponding index in language codes.

+        //

+        Index = GetIndexFromSupportedLangCodes (mGlobal->LangCodes, BestLang, TRUE);

+

+        //

+        // Get the corresponding RFC4646 language tag according to ISO639 language tag.

+        //

+        BestPlatformLang = GetLangFromSupportedLangCodes (mGlobal->PlatformLangCodes, Index, FALSE);

+

+        //

+        // Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.

+        //

+        FindVariable(L"PlatformLang", &gEfiGlobalVariableGuid, &Variable);

+

+        Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang, 

+                                 AsciiStrSize (BestPlatformLang), Attributes, &Variable);

+

+        DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));

+        ASSERT_EFI_ERROR (Status);

+      }

+    }

+  }

+}

+

+/**

+  Update the variable region with Variable information. These are the same 

+  arguments as the EFI Variable services.

+

+  @param[in] VariableName       Name of variable

+

+  @param[in] VendorGuid         Guid of variable

+

+  @param[in] Data               Variable data

+

+  @param[in] DataSize           Size of data. 0 means delete

+

+  @param[in] Attributes         Attribues of the variable

+

+  @param[in] Variable           The variable information which is used to keep track of variable usage.

+

+  @retval EFI_SUCCESS           The update operation is success.

+

+  @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.

+

+**/

+EFI_STATUS

+EFIAPI

+UpdateVariable (

+  IN      CHAR16                 *VariableName,

+  IN      EFI_GUID               *VendorGuid,

+  IN      VOID                   *Data,

+  IN      UINTN                  DataSize,

+  IN      UINT32                 Attributes OPTIONAL,

+  IN      VARIABLE_POINTER_TRACK *Variable

+  )

+{

+  EFI_STATUS                          Status;

+  VARIABLE_HEADER                     *NextVariable;

+  UINTN                               VarNameOffset;

+  UINTN                               VarDataOffset;

+  UINTN                               VarNameSize;

+  UINTN                               VarSize;

+  UINT8                               State;

+  BOOLEAN                             Reclaimed;

+  VARIABLE_STORAGE_TYPE               StorageType;

+

+  Reclaimed         = FALSE;

+

+  if (Variable->CurrPtr != NULL) {  

+    //

+    // Update/Delete existing variable

+    //

+    

+    if (EfiAtRuntime ()) {              

+      //

+      // If EfiAtRuntime and the variable is Volatile and Runtime Access,  

+      // the volatile is ReadOnly, and SetVariable should be aborted and 

+      // return EFI_WRITE_PROTECTED.

+      //

+      if (Variable->Type == Volatile) {

+        return EFI_WRITE_PROTECTED;

+      }

+      //

+      // Only variable have NV attribute can be updated/deleted in Runtime

+      //

+      if (!(Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE)) {

+        return EFI_INVALID_PARAMETER;      

+      }

+    }

+    

+    //

+    // Setting a data variable with no access, or zero DataSize attributes

+    // specified causes it to be deleted.

+    //

+    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {

+      //

+      // Found this variable in storage

+      //

+      State = Variable->CurrPtr->State;

+      State &= VAR_DELETED;

+

+      Status = mGlobal->VariableStore[Variable->Type]->Write (

+                                                        mGlobal->VariableStore[Variable->Type],

+                                                        VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr),

+                                                        sizeof (Variable->CurrPtr->State),

+                                                        &State

+                                                        );

+      //

+      // NOTE: Write operation at least can write data to memory cache

+      //       Discard file writing failure here.

+      //

+      return EFI_SUCCESS;

+    }

+    

+    //

+    // Found this variable in storage

+    // If the variable is marked valid and the same data has been passed in

+    // then return to the caller immediately.

+    //

+    if ((Variable->CurrPtr->DataSize == DataSize) &&

+        (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0)

+          ) {

+      return EFI_SUCCESS;

+    } else if ((Variable->CurrPtr->State == VAR_ADDED) ||

+               (Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {

+      //

+      // Mark the old variable as in delete transition

+      //

+      State = Variable->CurrPtr->State;

+      State &= VAR_IN_DELETED_TRANSITION;

+

+      Status = mGlobal->VariableStore[Variable->Type]->Write (

+                                                        mGlobal->VariableStore[Variable->Type],

+                                                        VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr),

+                                                        sizeof (Variable->CurrPtr->State),

+                                                        &State

+                                                        );

+      //

+      // NOTE: Write operation at least can write data to memory cache

+      //       Discard file writing failure here.

+      //

+    }

+  } else {

+    //

+    // Create a new variable

+    //  

+    

+    //

+    // Make sure we are trying to create a new variable.

+    // Setting a data variable with no access, or zero DataSize attributes means to delete it.    

+    //

+    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {

+      return EFI_NOT_FOUND;

+    }    

+    //

+    // Only variable have NV|RT attribute can be created in Runtime

+    //

+    if (EfiAtRuntime () &&

+        (!(Attributes & EFI_VARIABLE_RUNTIME_ACCESS) || !(Attributes & EFI_VARIABLE_NON_VOLATILE))) {

+      return EFI_INVALID_PARAMETER;

+    }        

+    

+  } 

+

+  //

+  // Function part - create a new variable and copy the data.

+  // Both update a variable and create a variable will come here.  

+  // We can firstly write all the data in memory, then write them to file

+  // This can reduce the times of write operation

+  //

+  

+  NextVariable = (VARIABLE_HEADER *) mGlobal->Scratch;

+

+  NextVariable->StartId     = VARIABLE_DATA;

+  NextVariable->Attributes  = Attributes;

+  NextVariable->State       = VAR_ADDED;

+  NextVariable->Reserved    = 0;

+  VarNameOffset             = sizeof (VARIABLE_HEADER);

+  VarNameSize               = StrSize (VariableName);

+  CopyMem (

+    (UINT8 *) ((UINTN) NextVariable + VarNameOffset),

+    VariableName,

+    VarNameSize

+    );

+  VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);

+  CopyMem (

+    (UINT8 *) ((UINTN) NextVariable + VarDataOffset),

+    Data,

+    DataSize

+    );

+  CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));

+  //

+  // There will be pad bytes after Data, the NextVariable->NameSize and

+  // NextVariable->DataSize should not include pad size so that variable

+  // service can get actual size in GetVariable

+  //

+  NextVariable->NameSize  = (UINT32)VarNameSize;

+  NextVariable->DataSize  = (UINT32)DataSize;

+

+  //

+  // The actual size of the variable that stores in storage should

+  // include pad size.

+  // VarDataOffset: offset from begin of current variable header

+  //

+  VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);

+

+  StorageType = (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile;

+

+  if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >

+      ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size

+      ) {

+    if ((StorageType == NonVolatile) && EfiAtRuntime ()) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+    //

+    // Perform garbage collection & reclaim operation

+    //

+    Status = Reclaim (StorageType, Variable->CurrPtr);

+    if (EFI_ERROR (Status)) {

+      //

+      // Reclaim error

+      // we cannot restore to original state, fetal error, report to user

+      //

+      DEBUG ((EFI_D_ERROR, "FSVariable: Recalim error (fetal error) - %r\n", Status));

+      return Status;

+    }

+    //

+    // If still no enough space, return out of resources

+    //

+    if ((UINT32) (VarSize + mGlobal->LastVariableOffset[StorageType]) >

+        ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[StorageType])->Size

+       ) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    Reclaimed = TRUE;

+  }

+  Status = mGlobal->VariableStore[StorageType]->Write (

+                                                  mGlobal->VariableStore[StorageType],

+                                                  mGlobal->LastVariableOffset[StorageType],

+                                                  VarSize,

+                                                  NextVariable

+                                                  );

+  //

+  // NOTE: Write operation at least can write data to memory cache

+  //       Discard file writing failure here.

+  //

+  mGlobal->LastVariableOffset[StorageType] += VarSize;

+

+  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {

+    mGlobal->HwErrVariableTotalSize += VarSize;

+  } else {

+    mGlobal->CommonVariableTotalSize += VarSize;

+  }

+

+  //

+  // Mark the old variable as deleted

+  //

+  if (!Reclaimed && !EFI_ERROR (Status) && Variable->CurrPtr != NULL) {

+    State = Variable->CurrPtr->State;

+    State &= VAR_DELETED;

+

+    Status = mGlobal->VariableStore[StorageType]->Write (

+                                                    mGlobal->VariableStore[StorageType],

+                                                    VARIABLE_MEMBER_OFFSET (State, (UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr),

+                                                    sizeof (Variable->CurrPtr->State),

+                                                    &State

+                                                    );

+    //

+    // NOTE: Write operation at least can write data to memory cache

+    //       Discard file writing failure here.

+    //

+  }

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+DuetGetVariable (

+  IN      CHAR16            *VariableName,

+  IN      EFI_GUID          *VendorGuid,

+  OUT     UINT32            *Attributes OPTIONAL,

+  IN OUT  UINTN             *DataSize,

+  OUT     VOID              *Data

+  )

+/*++

+

+Routine Description:

+

+  This code finds variable in storage blocks (Volatile or Non-Volatile)

+

+Arguments:

+

+  VariableName                    Name of Variable to be found

+  VendorGuid                      Variable vendor GUID

+  Attributes OPTIONAL             Attribute value of the variable found

+  DataSize                        Size of Data found. If size is less than the

+                                  data, this value contains the required size.

+  Data                            Data pointer

+

+Returns:

+

+  EFI STATUS

+

+--*/

+{

+  VARIABLE_POINTER_TRACK  Variable;

+  UINTN                   VarDataSize;

+  EFI_STATUS              Status;

+

+  if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Find existing variable

+  //

+  Status = FindVariable (VariableName, VendorGuid, &Variable);

+

+  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Get data size

+  //

+  VarDataSize = Variable.CurrPtr->DataSize;

+  if (*DataSize >= VarDataSize) {

+    if (Data == NULL) {

+      return EFI_INVALID_PARAMETER;

+    }

+    CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);

+

+    if (Attributes != NULL) {

+      *Attributes = Variable.CurrPtr->Attributes;

+    }

+

+    *DataSize = VarDataSize;

+

+    return EFI_SUCCESS;

+  } else {

+    *DataSize = VarDataSize;

+    return EFI_BUFFER_TOO_SMALL;

+  }

+}

+

+EFI_STATUS

+EFIAPI

+GetNextVariableName (

+  IN OUT  UINTN             *VariableNameSize,

+  IN OUT  CHAR16            *VariableName,

+  IN OUT  EFI_GUID          *VendorGuid

+  )

+/*++

+

+Routine Description:

+

+  This code Finds the Next available variable

+

+Arguments:

+

+  VariableNameSize            Size of the variable

+  VariableName                Pointer to variable name

+  VendorGuid                  Variable Vendor Guid

+

+Returns:

+

+  EFI STATUS

+

+--*/

+{

+  VARIABLE_POINTER_TRACK  Variable;

+  UINTN                   VarNameSize;

+  EFI_STATUS              Status;

+

+  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = FindVariable (VariableName, VendorGuid, &Variable);

+

+  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  if (VariableName[0] != 0) {

+    //

+    // If variable name is not NULL, get next variable

+    //

+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);

+  }

+

+  while (TRUE) {

+    //

+    // The order we find variable is: 1). NonVolatile; 2). Volatile

+    // If both volatile and non-volatile variable store are parsed,

+    // return not found

+    //

+    if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) {

+      if (Variable.Type == Volatile) {

+        //

+        // Since we met the end of Volatile storage, we have parsed all the stores.

+        //

+        return EFI_NOT_FOUND;

+      }

+

+      //

+      // End of NonVolatile, continue to parse Volatile

+      //

+      Variable.Type = Volatile;

+      Variable.StartPtr = (VARIABLE_HEADER *) ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Volatile] + 1);

+      Variable.EndPtr   = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) mGlobal->VariableBase[Volatile]);

+

+      Variable.CurrPtr = Variable.StartPtr;

+      if (!IsValidVariableHeader (Variable.CurrPtr)) {

+        continue;

+      }

+    }

+    //

+    // Variable is found

+    //

+    if (IsValidVariableHeader (Variable.CurrPtr) &&

+        ((Variable.CurrPtr->State == VAR_ADDED) ||

+         (Variable.CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)))) {

+      if (!EfiAtRuntime () || (Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {

+        VarNameSize = Variable.CurrPtr->NameSize;

+        if (VarNameSize <= *VariableNameSize) {

+          CopyMem (

+            VariableName,

+            GET_VARIABLE_NAME_PTR (Variable.CurrPtr),

+            VarNameSize

+            );

+          CopyMem (

+            VendorGuid,

+            &Variable.CurrPtr->VendorGuid,

+            sizeof (EFI_GUID)

+            );

+          Status = EFI_SUCCESS;

+        } else {

+          Status = EFI_BUFFER_TOO_SMALL;

+        }

+

+        *VariableNameSize = VarNameSize;

+        return Status;

+      }

+    }

+

+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);

+  }

+}

+

+EFI_STATUS

+EFIAPI

+SetVariable (

+  IN CHAR16                  *VariableName,

+  IN EFI_GUID                *VendorGuid,

+  IN UINT32                  Attributes,

+  IN UINTN                   DataSize,

+  IN VOID                    *Data

+  )

+/*++

+

+Routine Description:

+

+  This code sets variable in storage blocks (Volatile or Non-Volatile)

+

+Arguments:

+

+  VariableName                    Name of Variable to be found

+  VendorGuid                      Variable vendor GUID

+  Attributes                      Attribute value of the variable found

+  DataSize                        Size of Data found. If size is less than the

+                                  data, this value contains the required size.

+  Data                            Data pointer

+

+Returns:

+  

+  EFI_INVALID_PARAMETER           - Invalid parameter

+  EFI_SUCCESS                     - Set successfully

+  EFI_OUT_OF_RESOURCES            - Resource not enough to set variable

+  EFI_NOT_FOUND                   - Not found

+  EFI_DEVICE_ERROR                - Variable can not be saved due to hardware failure

+  EFI_WRITE_PROTECTED             - Variable is read-only

+

+--*/

+{

+  VARIABLE_POINTER_TRACK  Variable;

+  EFI_STATUS              Status;

+

+  //

+  // Check input parameters

+  // 

+  if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  if (DataSize != 0 && Data == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Not support authenticated variable write yet.

+  //

+  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  //  Make sure if runtime bit is set, boot service bit is set also

+  //

+  if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  //

+  //  The size of the VariableName, including the Unicode Null in bytes plus

+  //  the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)

+  //  bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.

+  //

+  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {

+    if ((DataSize > PcdGet32(PcdMaxHardwareErrorVariableSize)) ||                                                       

+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32(PcdMaxHardwareErrorVariableSize))) {

+      return EFI_INVALID_PARAMETER;

+    }

+    //

+    // According to UEFI spec, HARDWARE_ERROR_RECORD variable name convention should be L"HwErrRecXXXX"

+    //

+    if (StrnCmp(VariableName, L"HwErrRec", StrLen(L"HwErrRec")) != 0) {

+      return EFI_INVALID_PARAMETER;

+    }

+  } else {

+    if ((DataSize > PcdGet32(PcdMaxVariableSize)) ||

+        (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32(PcdMaxVariableSize))) {

+      return EFI_INVALID_PARAMETER;

+    }  

+  }  

+

+  //

+  // Check whether the input variable is already existed

+  //

+  Status = FindVariable (VariableName, VendorGuid, &Variable);

+

+  //

+  // Hook the operation of setting PlatformLangCodes/PlatformLang and LangCodes/Lang

+  //

+  AutoUpdateLangVariable (VariableName, Data, DataSize);

+

+  Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+QueryVariableInfo (

+  IN  UINT32                 Attributes,

+  OUT UINT64                 *MaximumVariableStorageSize,

+  OUT UINT64                 *RemainingVariableStorageSize,

+  OUT UINT64                 *MaximumVariableSize

+  )

+/*++

+

+Routine Description:

+

+  This code returns information about the EFI variables.

+

+Arguments:

+

+  Attributes                      Attributes bitmask to specify the type of variables

+                                  on which to return information.

+  MaximumVariableStorageSize      Pointer to the maximum size of the storage space available

+                                  for the EFI variables associated with the attributes specified.

+  RemainingVariableStorageSize    Pointer to the remaining size of the storage space available

+                                  for the EFI variables associated with the attributes specified.

+  MaximumVariableSize             Pointer to the maximum size of the individual EFI variables

+                                  associated with the attributes specified.

+

+Returns:

+

+  EFI STATUS

+  EFI_INVALID_PARAMETER           - An invalid combination of attribute bits was supplied.

+  EFI_SUCCESS                     - Query successfully.

+  EFI_UNSUPPORTED                 - The attribute is not supported on this platform.

+

+--*/

+{

+  VARIABLE_HEADER        *Variable;

+  VARIABLE_HEADER        *NextVariable;

+  UINT64                 VariableSize;

+  VARIABLE_STORE_HEADER  *VariableStoreHeader;

+  UINT64                 CommonVariableTotalSize;

+  UINT64                 HwErrVariableTotalSize;

+

+  CommonVariableTotalSize = 0;

+  HwErrVariableTotalSize = 0;

+

+  if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {

+    //

+    // Make sure the Attributes combination is supported by the platform.

+    //

+    return EFI_UNSUPPORTED;  

+  } else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {

+    //

+    // Make sure if runtime bit is set, boot service bit is set also.

+    //

+    return EFI_INVALID_PARAMETER;

+  } else if (EfiAtRuntime () && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {

+    //

+    // Make sure RT Attribute is set if we are in Runtime phase.

+    //

+    return EFI_INVALID_PARAMETER;

+  } else if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {

+    //

+    // Make sure Hw Attribute is set with NV.

+    //

+    return EFI_INVALID_PARAMETER;

+  } else if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {

+    //

+    // Not support authentiated variable write yet.

+    //

+    return EFI_UNSUPPORTED;

+  }

+  

+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) mGlobal->VariableBase[

+                                (Attributes & EFI_VARIABLE_NON_VOLATILE) ? NonVolatile : Volatile

+                                ];

+  //

+  // Now let's fill *MaximumVariableStorageSize *RemainingVariableStorageSize

+  // with the storage size (excluding the storage header size).

+  //

+  *MaximumVariableStorageSize   = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);

+

+  //

+  // Harware error record variable needs larger size.

+  //

+  if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+    *MaximumVariableStorageSize = PcdGet32(PcdHwErrStorageSize);

+    *MaximumVariableSize = PcdGet32(PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);

+  } else {

+    if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {

+      ASSERT (PcdGet32(PcdHwErrStorageSize) < VariableStoreHeader->Size);

+      *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32(PcdHwErrStorageSize);

+    }

+

+    //

+    // Let *MaximumVariableSize be PcdGet32(PcdMaxVariableSize) with the exception of the variable header size.

+    //

+    *MaximumVariableSize = PcdGet32(PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);

+  }

+  

+  //

+  // Point to the starting address of the variables.

+  //

+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

+

+  //

+  // Now walk through the related variable store.

+  //

+  while ((Variable < GetEndPointer (VariableStoreHeader)) && IsValidVariableHeader (Variable)) {

+    NextVariable = GetNextVariablePtr (Variable);

+    VariableSize = (UINT64) (UINTN) NextVariable - (UINT64) (UINTN) Variable;

+

+    if (EfiAtRuntime ()) {

+      //

+      // we don't take the state of the variables in mind

+      // when calculating RemainingVariableStorageSize,

+      // since the space occupied by variables not marked with

+      // VAR_ADDED is not allowed to be reclaimed in Runtime.

+      //

+      if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {

+        HwErrVariableTotalSize += VariableSize;

+      } else {

+        CommonVariableTotalSize += VariableSize;

+      }

+    } else {

+      //

+      // Only care about Variables with State VAR_ADDED,because

+      // the space not marked as VAR_ADDED is reclaimable now.

+      //

+      if ((Variable->State == VAR_ADDED) || (Variable->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {

+        if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {

+          HwErrVariableTotalSize += VariableSize;

+        } else {

+          CommonVariableTotalSize += VariableSize;

+        }

+      }

+    }

+

+    //

+    // Go to the next one

+    //

+    Variable = NextVariable;

+  }

+  

+  if ((Attributes  & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){

+    *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;

+  } else {

+    *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+VariableServiceInitialize (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+/*++

+

+Routine Description:

+  This function does initialization for variable services

+

+Arguments:

+

+  ImageHandle   - The firmware allocated handle for the EFI image.

+  SystemTable   - A pointer to the EFI System Table.

+

+Returns:

+

+  Status code.

+

+  EFI_NOT_FOUND     - Variable store area not found.

+  EFI_SUCCESS       - Variable services successfully initialized.

+

+--*/

+{

+  EFI_STATUS                      Status;

+  EFI_HANDLE                      NewHandle;

+  VS_DEV                          *Dev;

+  EFI_PEI_HOB_POINTERS            GuidHob;

+  VARIABLE_HEADER                 *Variable;

+  VARIABLE_HEADER                 *NextVariable;

+  VARIABLE_STORE_HEADER           *VariableStoreHeader;

+  EFI_FLASH_MAP_FS_ENTRY_DATA     *FlashMapEntryData;

+  EFI_FLASH_SUBAREA_ENTRY         VariableStoreEntry;

+  UINT64                          BaseAddress;

+  UINT64                          Length;

+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;

+

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  (UINTN) sizeof (VARIABLE_GLOBAL),

+                  (VOID**) &mGlobal

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  ZeroMem (mGlobal, (UINTN) sizeof (VARIABLE_GLOBAL));

+

+  GuidHob.Raw = GetHobList ();

+  FlashMapEntryData = NULL;

+  while ((GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw)) != NULL) {

+    FlashMapEntryData = (EFI_FLASH_MAP_FS_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid);

+    if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) {

+      break;

+    }

+    GuidHob.Raw = GET_NEXT_HOB (GuidHob); 

+  }

+

+  if (FlashMapEntryData == NULL) {

+    DEBUG ((EFI_D_ERROR, "FSVariable: Could not find flash area for variable!\n"));

+    Status = EFI_NOT_FOUND;

+    return Status;

+  }

+  

+  CopyMem(

+    (VOID*)&VariableStoreEntry,

+    (VOID*)&FlashMapEntryData->Entries[0],

+    sizeof(EFI_FLASH_SUBAREA_ENTRY)

+    );

+

+  //

+  // Mark the variable storage region of the FLASH as RUNTIME

+  //

+  BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK);

+  Length      = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress);

+  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);

+  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);

+  if (EFI_ERROR (Status)) {

+    Status = EFI_UNSUPPORTED;

+    return Status;

+  }

+  Status = gDS->SetMemorySpaceAttributes (

+                  BaseAddress,

+                  Length,

+                  GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME

+                  );

+  if (EFI_ERROR (Status)) {

+    Status = EFI_UNSUPPORTED;

+    return Status;

+  }

+

+  Status = FileStorageConstructor (

+             &mGlobal->VariableStore[NonVolatile], 

+             &mGlobal->GoVirtualChildEvent[NonVolatile],

+             VariableStoreEntry.Base,

+             (UINT32) VariableStoreEntry.Length,

+             FlashMapEntryData->VolumeId,

+             FlashMapEntryData->FilePath

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Volatile Storage

+  //

+  Status = MemStorageConstructor (

+             &mGlobal->VariableStore[Volatile],

+             &mGlobal->GoVirtualChildEvent[Volatile],

+             VOLATILE_VARIABLE_STORE_SIZE

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Scratch

+  //

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  VARIABLE_SCRATCH_SIZE,

+                  &mGlobal->Scratch

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // 1. NV Storage

+  //

+  Dev = DEV_FROM_THIS (mGlobal->VariableStore[NonVolatile]);

+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);

+  if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {

+    if (~VariableStoreHeader->Size == 0) {

+      VariableStoreHeader->Size = (UINT32) VariableStoreEntry.Length;

+    }

+  }

+  //

+  // Calculate LastVariableOffset

+  //

+  Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1);

+  while (IsValidVariableHeader (Variable)) {

+    UINTN VariableSize = 0;

+    NextVariable = GetNextVariablePtr (Variable);

+    VariableSize = NextVariable - Variable;

+    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {

+      mGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);

+    } else {

+      mGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);

+    }

+    Variable = NextVariable;

+  }

+

+  mGlobal->LastVariableOffset[NonVolatile] = (UINTN) Variable - (UINTN) VariableStoreHeader;

+  mGlobal->VariableBase[NonVolatile]       = VariableStoreHeader;

+

+  //

+  // Reclaim if remaining space is too small

+  //

+  if ((VariableStoreHeader->Size - mGlobal->LastVariableOffset[NonVolatile]) < VARIABLE_RECLAIM_THRESHOLD) {

+    Status = Reclaim (NonVolatile, NULL);

+    if (EFI_ERROR (Status)) {

+      //

+      // Reclaim error

+      // we cannot restore to original state

+      //

+      DEBUG ((EFI_D_ERROR, "FSVariable: Reclaim error (fatal error) - %r\n", Status));

+      ASSERT_EFI_ERROR (Status);

+    }

+  }

+  

+  //

+  // 2. Volatile Storage

+  //

+  Dev = DEV_FROM_THIS (mGlobal->VariableStore[Volatile]);

+  VariableStoreHeader = (VARIABLE_STORE_HEADER *) VAR_DATA_PTR (Dev);

+  mGlobal->VariableBase[Volatile] = VAR_DATA_PTR (Dev);  

+  mGlobal->LastVariableOffset[Volatile] = sizeof (VARIABLE_STORE_HEADER);

+  //

+  // init store_header & body in memory.

+  //

+  mGlobal->VariableStore[Volatile]->Erase (mGlobal->VariableStore[Volatile]);

+  mGlobal->VariableStore[Volatile]->Write (

+                                   mGlobal->VariableStore[Volatile],

+                                   0,

+                                   sizeof (VARIABLE_STORE_HEADER),

+                                   &mStoreHeaderTemplate

+                                   );

+

+

+  SystemTable->RuntimeServices->GetVariable         = DuetGetVariable;

+  SystemTable->RuntimeServices->GetNextVariableName = GetNextVariableName;

+  SystemTable->RuntimeServices->SetVariable         = SetVariable;

+

+  SystemTable->RuntimeServices->QueryVariableInfo   = QueryVariableInfo;

+

+  //

+  // Now install the Variable Runtime Architectural Protocol on a new handle

+  //

+  NewHandle = NULL;

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &NewHandle,

+                  &gEfiVariableArchProtocolGuid,

+                  NULL,

+                  &gEfiVariableWriteArchProtocolGuid,

+                  NULL,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

+

+

+

+VOID

+EFIAPI

+OnVirtualAddressChangeFsv (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  )

+{

+  UINTN Index;

+

+  for (Index = 0; Index < MaxType; Index++) {

+    mGlobal->GoVirtualChildEvent[Index] (Event, mGlobal->VariableStore[Index]);

+    EfiConvertPointer (0, (VOID**) &mGlobal->VariableStore[Index]);

+    EfiConvertPointer (0, &mGlobal->VariableBase[Index]);

+  }

+  EfiConvertPointer (0, (VOID **) &mGlobal->PlatformLangCodes);

+  EfiConvertPointer (0, (VOID **) &mGlobal->LangCodes);

+  EfiConvertPointer (0, (VOID **) &mGlobal->PlatformLang);

+  EfiConvertPointer (0, &mGlobal->Scratch);

+  EfiConvertPointer (0, (VOID**) &mGlobal);

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.h b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.h
new file mode 100644
index 0000000..cc39323
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.h
@@ -0,0 +1,162 @@
+/*++

+

+Caution: This file is used for Duet platform only, do not use them in real platform.

+All variable code, variable metadata, and variable data used by Duet platform are on 

+disk. They can be changed by user. BIOS is not able to protoect those.

+Duet trusts all meta data from disk. If variable code, variable metadata and variable

+data is modified in inproper way, the behavior is undefined.

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FSVariable.h

+  

+Abstract:

+

+--*/

+

+#ifndef _FS_VARIABLE_H

+#define _FS_VARIABLE_H

+

+//

+// Statements that include other header files

+//

+#include <PiDxe.h>

+

+#include <Library/BaseLib.h>

+#include <Library/PcdLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiRuntimeLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiLib.h>

+#include <Library/HobLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/DevicePathLib.h>

+

+#include <Guid/HobList.h>

+#include <Guid/FlashMapHob.h>

+#include <Guid/VariableFormat.h>

+#include <Guid/GlobalVariable.h>

+#include <Protocol/Variable.h>

+#include <Protocol/VariableWrite.h>

+#include <Protocol/SimpleFileSystem.h>

+#include <Protocol/BlockIo.h>

+

+

+#include "EfiFlashMap.h"

+#include "VariableStorage.h"

+

+#define VOLATILE_VARIABLE_STORE_SIZE  FixedPcdGet32(PcdVariableStoreSize)

+#define VARIABLE_SCRATCH_SIZE         MAX(FixedPcdGet32(PcdMaxVariableSize), FixedPcdGet32(PcdMaxHardwareErrorVariableSize))

+#define VARIABLE_RECLAIM_THRESHOLD    (1024)

+///

+/// The size of a 3 character ISO639 language code.

+///

+#define ISO_639_2_ENTRY_SIZE    3

+

+#define GET_VARIABLE_NAME_PTR(a)  (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER))

+

+typedef enum {

+  Physical,

+  Virtual

+} VARIABLE_POINTER_TYPE;

+

+typedef enum {

+  NonVolatile,

+  Volatile,

+  MaxType

+} VARIABLE_STORAGE_TYPE;

+

+typedef struct {

+  VARIABLE_HEADER         *CurrPtr;

+  VARIABLE_HEADER         *EndPtr;

+  VARIABLE_HEADER         *StartPtr;

+  VARIABLE_STORAGE_TYPE   Type;

+} VARIABLE_POINTER_TRACK;

+

+#define VARIABLE_MEMBER_OFFSET(Member, StartOffset) \

+        ( sizeof (VARIABLE_STORE_HEADER) + (StartOffset) + \

+          (UINTN) ((UINT8 *) &((VARIABLE_HEADER*) 0)->Member - (UINT8 *) &((VARIABLE_HEADER*) 0)->StartId) \

+        )

+

+

+typedef struct {

+  EFI_EVENT_NOTIFY   GoVirtualChildEvent[MaxType];

+  VARIABLE_STORAGE   *VariableStore[MaxType];       // Instance of VariableStorage

+  VOID               *VariableBase[MaxType];        // Start address of variable storage

+  UINTN              LastVariableOffset[MaxType];   // The position to write new variable to (index from VariableBase)

+  VOID               *Scratch;                      // Buffer used during reclaim

+  UINTN              CommonVariableTotalSize;

+  UINTN              HwErrVariableTotalSize;

+  CHAR8              *PlatformLangCodes;

+  CHAR8              *LangCodes;

+  CHAR8              *PlatformLang;

+  CHAR8              Lang[ISO_639_2_ENTRY_SIZE + 1];

+} VARIABLE_GLOBAL;

+

+//

+// Functions

+//

+

+EFI_STATUS

+EFIAPI

+VariableServiceInitialize (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  );

+

+VOID

+EFIAPI

+VariableClassAddressChangeEvent (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  );

+

+EFI_STATUS

+EFIAPI

+DuetGetVariable (

+  IN      CHAR16            *VariableName,

+  IN      EFI_GUID          *VendorGuid,

+  OUT     UINT32            *Attributes OPTIONAL,

+  IN OUT  UINTN             *DataSize,

+  OUT     VOID              *Data

+  );

+

+EFI_STATUS

+EFIAPI

+GetNextVariableName (

+  IN OUT  UINTN             *VariableNameSize,

+  IN OUT  CHAR16            *VariableName,

+  IN OUT  EFI_GUID          *VendorGuid

+  );

+

+EFI_STATUS

+EFIAPI

+SetVariable (

+  IN CHAR16                  *VariableName,

+  IN EFI_GUID                *VendorGuid,

+  IN UINT32                  Attributes,

+  IN UINTN                   DataSize,

+  IN VOID                    *Data

+  );

+

+EFI_STATUS

+EFIAPI

+QueryVariableInfo (

+  IN  UINT32                 Attributes,

+  OUT UINT64                 *MaximumVariableStorageSize,

+  OUT UINT64                 *RemainingVariableStorageSize,

+  OUT UINT64                 *MaximumVariableSize

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.inf b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.inf
new file mode 100644
index 0000000..ad9037a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/FSVariable.inf
@@ -0,0 +1,80 @@
+## @file

+#

+# Caution: This file is used for Duet platform only, do not use them in real platform.

+# All variable code, variable metadata, and variable data used by Duet platform are on 

+# disk. They can be changed by user. BIOS is not able to protoect those.

+# Duet trusts all meta data from disk. If variable code, variable metadata and variable

+# data is modified in inproper way, the behavior is undefined.

+#

+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+# 

+#  Module Name:

+#

+#   FSVariable.inf

+#

+#  Abstract:

+#

+#    Component description file for variable module

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = FSVariable

+  FILE_GUID                      = A36495C1-C205-414e-B71F-4BE3476D699C

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = VariableServiceInitialize

+  

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+

+[Sources]

+  FSVariable.h

+  VariableStorage.h

+  FSVariable.c

+  FileStorage.c

+  MemStorage.c

+

+[LibraryClasses]

+  PcdLib

+  BaseMemoryLib

+  BaseLib

+  UefiBootServicesTableLib

+  UefiRuntimeLib

+  DebugLib

+  UefiLib

+  HobLib

+  DxeServicesTableLib

+  DevicePathLib

+  UefiDriverEntryPoint

+  MemoryAllocationLib

+

+[Guids]

+  gEfiFlashMapHobGuid

+  gEfiVariableGuid

+  gEfiGlobalVariableGuid                        ## PRODUCES ## Variable Guid

+  

+[Protocols]

+  gEfiVariableArchProtocolGuid

+  gEfiVariableWriteArchProtocolGuid

+  gEfiSimpleFileSystemProtocolGuid

+  gEfiBlockIoProtocolGuid

+

+[Pcd]

+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize

+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize

+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize

+  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize

+

+[Depex]

+  TRUE

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/FileStorage.c b/uefi/linaro-edk2/DuetPkg/FSVariable/FileStorage.c
new file mode 100644
index 0000000..d07c0bb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/FileStorage.c
@@ -0,0 +1,437 @@
+/*++

+

+Caution: This file is used for Duet platform only, do not use them in real platform.

+All variable code, variable metadata, and variable data used by Duet platform are on 

+disk. They can be changed by user. BIOS is not able to protoect those.

+Duet trusts all meta data from disk. If variable code, variable metadata and variable

+data is modified in inproper way, the behavior is undefined.

+

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

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+    FileStorage.c

+

+Abstract:

+

+    handles variable store/reads on file

+

+Revision History

+

+--*/

+#include "FSVariable.h"

+

+VOID             *mSFSRegistration;

+

+//

+// Prototypes

+//

+

+VOID

+EFIAPI

+OnVirtualAddressChangeFs (

+  IN EFI_EVENT            Event,

+  IN VOID                 *Context

+  );

+

+EFI_STATUS

+EFIAPI

+FileEraseStore(

+  IN VARIABLE_STORAGE     *This

+  );

+

+EFI_STATUS

+EFIAPI

+FileWriteStore (

+  IN VARIABLE_STORAGE     *This,

+  IN UINTN                Offset,

+  IN UINTN                BufferSize,

+  IN VOID                 *Buffer

+  );

+

+EFI_STATUS

+OpenStore (

+  IN  EFI_DEVICE_PATH_PROTOCOL  *Device,

+  IN  CHAR16                    *FilePathName,

+  IN  UINT64                    OpenMode,

+  OUT EFI_FILE_PROTOCOL         **File

+  );

+

+//

+// Implementation below:

+//

+VOID

+FileClose (

+  IN  EFI_FILE_PROTOCOL          *File

+  )

+{

+  EFI_STATUS Status;

+

+  Status = File->Flush (File);

+  ASSERT_EFI_ERROR (Status);

+

+  Status = File->Close (File);

+  ASSERT_EFI_ERROR (Status);

+}

+

+EFI_STATUS

+CheckStore (

+  IN  EFI_HANDLE                 SimpleFileSystemHandle,

+  IN  UINT32                     VolumeId,

+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device

+  )

+{

+#define BLOCK_SIZE              0x200

+#define FAT16_VOLUME_ID_OFFSET  39

+#define FAT32_VOLUME_ID_OFFSET  67

+  EFI_STATUS                      Status;

+  EFI_BLOCK_IO_PROTOCOL           *BlkIo;

+  UINT8                           BootSector[BLOCK_SIZE];

+

+  *Device = NULL;

+  Status  = gBS->HandleProtocol (

+                   SimpleFileSystemHandle,

+                   &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem

+                   (VOID*)&BlkIo

+                   );

+

+  if (EFI_ERROR (Status)) {

+    goto ErrHandle;

+  }

+  if (!BlkIo->Media->MediaPresent) {

+    DEBUG ((EFI_D_ERROR, "FileStorage: Media not present!\n"));

+    Status = EFI_NO_MEDIA;

+    goto ErrHandle;

+  }

+  if (BlkIo->Media->ReadOnly) {

+    DEBUG ((EFI_D_ERROR, "FileStorage: Media is read-only!\n"));

+    Status = EFI_ACCESS_DENIED;

+    goto ErrHandle;

+  }

+

+  Status = BlkIo->ReadBlocks(

+                    BlkIo,

+                    BlkIo->Media->MediaId,

+                    0,

+                    BLOCK_SIZE,

+                    BootSector

+                    );

+  ASSERT_EFI_ERROR (Status);

+  if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&

+      (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)

+      ) {

+    Status = EFI_NOT_FOUND;

+    goto ErrHandle;

+  }

+

+  *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));

+  ASSERT (*Device != NULL);

+

+ErrHandle:

+  return Status;

+}

+

+EFI_STATUS

+CheckStoreExists (

+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device

+  )

+{

+  EFI_HANDLE                        Handle;

+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;

+  EFI_STATUS                        Status;

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Device, 

+                  &Handle

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->HandleProtocol (

+                  Handle,

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  (VOID **) &Volume

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+// this routine is still running in BS period, no limitation

+// call FileInitStorage(), which load variable content file to memory

+// read the store_header, init store_header if it has not been inited (read sth. about format/heathy)

+// reclaim space using scratch memory

+

+VOID

+EFIAPI

+OnSimpleFileSystemInstall (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  )

+{

+  EFI_STATUS                Status;

+  UINTN                     HandleSize;

+  EFI_HANDLE                Handle;

+  EFI_DEVICE_PATH_PROTOCOL  *Device;

+  VS_DEV                    *Dev;

+  EFI_FILE_PROTOCOL         *File;

+  UINTN                     NumBytes;

+

+  Dev = (VS_DEV *) Context;

+  

+  if (VAR_FILE_DEVICEPATH (Dev) != NULL &&

+      !EFI_ERROR (CheckStoreExists (VAR_FILE_DEVICEPATH (Dev)))

+     ) {

+    DEBUG ((EFI_D_ERROR, "FileStorage: Already mapped!\n"));

+    return ;

+  }

+

+  while (TRUE) {

+    HandleSize = sizeof (EFI_HANDLE);

+    Status = gBS->LocateHandle (

+                    ByRegisterNotify,

+                    NULL,

+                    mSFSRegistration,

+                    &HandleSize,

+                    &Handle

+                    );

+    if (EFI_ERROR (Status)) {

+      return ;

+    }

+    

+    Status = CheckStore (Handle, VAR_FILE_VOLUMEID (Dev), &Device);

+    if (!EFI_ERROR (Status)) {

+      break;

+    }

+  }

+

+  VAR_FILE_DEVICEPATH (Dev) = Device;

+  Status = OpenStore (

+             VAR_FILE_DEVICEPATH (Dev), 

+             VAR_FILE_FILEPATH (Dev), 

+             EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE,

+             &File

+             );

+  ASSERT_EFI_ERROR (Status);

+  

+  NumBytes = Dev->Size;

+  Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));

+  ASSERT_EFI_ERROR (Status);

+  FileClose (File);

+  DEBUG ((EFI_D_ERROR, "FileStorage: Mapped to file!\n"));

+}

+

+EFI_STATUS

+FileStorageConstructor (

+  OUT VARIABLE_STORAGE      **VarStore,

+  OUT EFI_EVENT_NOTIFY      *GoVirtualEvent,

+  IN  EFI_PHYSICAL_ADDRESS  NvStorageBase,

+  IN  UINTN                 Size,

+  IN  UINT32                VolumeId,

+  IN  CHAR16                *FilePath

+  )

+{

+  VS_DEV                    *Dev;

+  EFI_STATUS                Status;

+  EFI_EVENT                 Event;

+

+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), (VOID **) &Dev);

+  ASSERT_EFI_ERROR (Status);

+  ZeroMem (Dev, sizeof(VS_DEV));

+

+  Dev->Signature          = VS_DEV_SIGNATURE;

+  Dev->Size               = Size;

+  VAR_DATA_PTR (Dev)      = (UINT8 *) (UINTN) NvStorageBase;

+  VAR_FILE_VOLUMEID (Dev) = VolumeId;

+  StrCpy (VAR_FILE_FILEPATH (Dev), FilePath);

+  Dev->VarStore.Erase     = FileEraseStore;

+  Dev->VarStore.Write     = FileWriteStore;

+

+  DEBUG ((EFI_D_ERROR, "FileStorageConstructor(0x%0x:0x%0x): added!\n", NvStorageBase, Size));

+

+  // add notify on SFS's installation.

+

+  Status = gBS->CreateEvent (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  OnSimpleFileSystemInstall,

+                  Dev,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->RegisterProtocolNotify (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  Event,

+                  &mSFSRegistration

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  *VarStore       = &Dev->VarStore;

+  *GoVirtualEvent = OnVirtualAddressChangeFs;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+FileEraseStore(

+  IN VARIABLE_STORAGE   *This

+  )

+{

+  EFI_STATUS              Status;

+  VS_DEV                  *Dev;

+  EFI_FILE_PROTOCOL       *File;

+  UINTN                   NumBytes;

+

+  Status = EFI_SUCCESS;

+  Dev    = DEV_FROM_THIS(This);

+

+  SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);

+

+  if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {

+    Status = OpenStore (

+               VAR_FILE_DEVICEPATH (Dev), 

+               VAR_FILE_FILEPATH (Dev), 

+               EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,

+               &File

+               );

+    ASSERT_EFI_ERROR (Status);

+    NumBytes = Dev->Size;

+    Status = File->Write (File, &NumBytes, VAR_DATA_PTR (Dev));

+    ASSERT_EFI_ERROR (Status);

+    FileClose (File);

+  }

+  

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+FileWriteStore (

+  IN VARIABLE_STORAGE     *This,

+  IN UINTN                Offset,

+  IN UINTN                BufferSize,

+  IN VOID                 *Buffer

+  )

+{

+  EFI_STATUS              Status;

+  VS_DEV                  *Dev;

+  EFI_FILE_PROTOCOL       *File;

+

+  Status = EFI_SUCCESS;

+  Dev    = DEV_FROM_THIS(This);

+

+  ASSERT (Buffer != NULL);

+  ASSERT (Offset + BufferSize <= Dev->Size);

+

+  CopyMem (VAR_DATA_PTR (Dev) + Offset, Buffer, BufferSize);

+  

+  if (!EfiAtRuntime () && VAR_FILE_DEVICEPATH (Dev) != NULL) {

+    Status = OpenStore (

+               VAR_FILE_DEVICEPATH (Dev), 

+               VAR_FILE_FILEPATH (Dev), 

+               EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ,

+               &File

+               );

+    Status = File->SetPosition (File, Offset);

+    ASSERT_EFI_ERROR (Status);

+    Status = File->Write (File, &BufferSize, Buffer);

+    ASSERT_EFI_ERROR (Status);

+    FileClose (File);

+  }

+  return Status;

+}

+

+VOID

+EFIAPI

+OnVirtualAddressChangeFs (

+  IN EFI_EVENT            Event,

+  IN VOID                 *Context

+  )

+{

+  VS_DEV  *Dev;

+

+  Dev = DEV_FROM_THIS (Context);

+

+  EfiConvertPointer (0, (VOID **) &VAR_DATA_PTR (Dev));

+  EfiConvertPointer (0, (VOID **) &Dev->VarStore.Erase);

+  EfiConvertPointer (0, (VOID **) &Dev->VarStore.Write);

+}

+

+EFI_STATUS

+OpenStore (

+  IN  EFI_DEVICE_PATH_PROTOCOL  *Device,

+  IN  CHAR16                    *FilePathName,

+  IN  UINT64                    OpenMode,

+  OUT EFI_FILE_PROTOCOL         **File

+  )

+{

+  EFI_HANDLE                        Handle;

+  EFI_FILE_HANDLE                   Root;

+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;

+  EFI_STATUS                        Status;

+

+  *File = NULL;

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Device, 

+                  &Handle

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->HandleProtocol (

+                  Handle,

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  (VOID **) &Volume

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Open the root directory of the volume

+  //

+  Root = NULL;

+  Status = Volume->OpenVolume (

+                     Volume,

+                     &Root

+                     );

+  ASSERT_EFI_ERROR (Status);

+  ASSERT (Root != NULL);

+

+  //

+  // Open file

+  //

+  Status = Root->Open (

+                   Root,

+                   File,

+                   FilePathName,

+                   OpenMode,

+                   0

+                   );

+  if (EFI_ERROR (Status)) {

+    *File = NULL;

+  }

+

+  //

+  // Close the Root directory

+  //

+  Root->Close (Root);

+  return Status;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/MemStorage.c b/uefi/linaro-edk2/DuetPkg/FSVariable/MemStorage.c
new file mode 100644
index 0000000..cc0d546
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/MemStorage.c
@@ -0,0 +1,135 @@
+/*++

+

+Caution: This file is used for Duet platform only, do not use them in real platform.

+All variable code, variable metadata, and variable data used by Duet platform are on 

+disk. They can be changed by user. BIOS is not able to protoect those.

+Duet trusts all meta data from disk. If variable code, variable metadata and variable

+data is modified in inproper way, the behavior is undefined.

+

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

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+    MemStorage.c

+

+Abstract:

+

+    handles variable store/reads with emulated memory

+

+Revision History

+

+--*/

+#include "FSVariable.h"

+

+VOID

+EFIAPI

+OnVirtualAddressChangeMs (

+  IN EFI_EVENT            Event,

+  IN VOID                 *Context

+  );

+

+EFI_STATUS

+EFIAPI

+MemEraseStore(

+  IN VARIABLE_STORAGE   *This

+  );

+

+EFI_STATUS

+EFIAPI

+MemWriteStore (

+  IN VARIABLE_STORAGE   *This,

+  IN UINTN                Offset,

+  IN UINTN                BufferSize,

+  IN VOID                 *Buffer

+  );

+

+EFI_STATUS

+MemStorageConstructor (

+  OUT VARIABLE_STORAGE          **VarStore,

+  OUT EFI_EVENT_NOTIFY          *GoVirtualEvent,

+  IN  UINTN                     Size

+  )

+{

+  EFI_STATUS                  Status;

+  VS_DEV                      *Dev;

+

+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof(VS_DEV), (VOID **) &Dev);

+  ASSERT_EFI_ERROR (Status);

+

+  ZeroMem (Dev, sizeof(VS_DEV));

+

+  Dev->Signature   = VS_DEV_SIGNATURE;

+  Dev->Size        = Size;

+

+  Dev->VarStore.Erase    = MemEraseStore;

+  Dev->VarStore.Write    = MemWriteStore;

+

+  Status = gBS->AllocatePool (EfiRuntimeServicesData, Size, (VOID **) &VAR_DATA_PTR (Dev));

+  ASSERT_EFI_ERROR (Status);

+

+  DEBUG ((EFI_D_ERROR, "VStorage: Size = 0x%x\n", Size));

+  

+  *VarStore       = &Dev->VarStore;

+  *GoVirtualEvent = OnVirtualAddressChangeMs;

+

+  return EFI_SUCCESS;

+}

+

+VOID

+EFIAPI

+OnVirtualAddressChangeMs (

+  IN EFI_EVENT            Event,

+  IN VOID                 *Context

+  )

+{

+  VS_DEV                  *Dev;

+

+  Dev = DEV_FROM_THIS (Context);

+

+  EfiConvertPointer (0, (VOID **)&VAR_DATA_PTR (Dev));

+  EfiConvertPointer (0, (VOID **)&Dev->VarStore.Erase);

+  EfiConvertPointer (0, (VOID **)&Dev->VarStore.Write);

+}

+

+EFI_STATUS

+EFIAPI

+MemEraseStore(

+  IN VARIABLE_STORAGE   *This

+  )

+{

+  VS_DEV              *Dev;

+

+  Dev = DEV_FROM_THIS(This);

+  SetMem (VAR_DATA_PTR (Dev), Dev->Size, VAR_DEFAULT_VALUE);

+  return EFI_SUCCESS;

+}

+

+

+EFI_STATUS

+EFIAPI

+MemWriteStore (

+  IN VARIABLE_STORAGE     *This,

+  IN UINTN                Offset,

+  IN UINTN                BufferSize,

+  IN VOID                 *UserBuffer

+  )

+{

+  VS_DEV              *Dev;

+

+  Dev = DEV_FROM_THIS(This);

+

+  ASSERT (Offset + BufferSize < Dev->Size);

+

+  // For better performance

+  if (VAR_DATA_PTR (Dev) + Offset != UserBuffer) {

+    CopyMem (VAR_DATA_PTR (Dev) + Offset, UserBuffer, BufferSize);

+  }

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FSVariable/VariableStorage.h b/uefi/linaro-edk2/DuetPkg/FSVariable/VariableStorage.h
new file mode 100644
index 0000000..48cbd5d
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FSVariable/VariableStorage.h
@@ -0,0 +1,118 @@
+/*++

+

+Caution: This file is used for Duet platform only, do not use them in real platform.

+All variable code, variable metadata, and variable data used by Duet platform are on 

+disk. They can be changed by user. BIOS is not able to protoect those.

+Duet trusts all meta data from disk. If variable code, variable metadata and variable

+data is modified in inproper way, the behavior is undefined.

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    VariableStorage.h

+

+Abstract:

+

+    handles variable store/reads with memory and file

+

+Revision History

+

+--*/

+#ifndef _VARIABLE_STORAGE_H_

+#define _VARIABLE_STORAGE_H_

+

+#define VAR_DEFAULT_VALUE           (0xff)

+#define VAR_DEFAULT_VALUE_16        SIGNATURE_16 (VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE)

+#define VAR_DEFAULT_VALUE_32        SIGNATURE_32 (VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE, \

+                                                      VAR_DEFAULT_VALUE, VAR_DEFAULT_VALUE)

+

+typedef struct _VARIABLE_STORAGE VARIABLE_STORAGE;

+

+EFI_STATUS

+FileStorageConstructor (

+  OUT VARIABLE_STORAGE      **VarStore,

+  OUT EFI_EVENT_NOTIFY      *GoVirtualEvent,

+  IN  EFI_PHYSICAL_ADDRESS  NvStorageBase,

+  IN  UINTN                 Size,

+  IN  UINT32                VolumeId,

+  IN  CHAR16                *FilePath

+  );

+

+EFI_STATUS

+MemStorageConstructor (

+  OUT VARIABLE_STORAGE          **VarStore,

+  OUT EFI_EVENT_NOTIFY          *GoVirtualEvent,

+  IN  UINTN                     Size

+  );

+

+typedef

+EFI_STATUS

+(EFIAPI *ERASE_STORE) (

+  IN VARIABLE_STORAGE   *This

+  );

+

+typedef

+EFI_STATUS

+(EFIAPI *WRITE_STORE) (

+  IN VARIABLE_STORAGE   *This,

+  IN UINTN              Offset,

+  IN UINTN              BufferSize,

+  IN VOID               *Buffer

+  );

+

+struct _VARIABLE_STORAGE {

+

+  //

+  // Functions to access the storage

+  //

+  ERASE_STORE           Erase;

+  WRITE_STORE           Write;

+};

+

+typedef struct _VS_FILE_INFO {

+  UINT8                     *FileData;      // local buffer for reading acceleration

+

+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;    // device having storage file

+  UINT32                    VolumeId;

+  CHAR16                    FilePath[256];

+} VS_FILE_INFO;

+

+typedef struct _VS_MEM_INFO {

+  UINT8                     *MemData;

+} VS_MEM_INFO;

+

+typedef struct _VS_DEV {

+  UINT32             Signature;

+  VARIABLE_STORAGE   VarStore;

+  UINTN              Size;

+  

+  union {

+    //

+    // finally visit FileInfo.FileData or MemInfo.MemData

+    //

+    UINT8            *Data;

+    

+    VS_FILE_INFO     FileInfo;

+    VS_MEM_INFO      MemInfo;

+  } Info;

+

+} VS_DEV;

+

+#define VS_DEV_SIGNATURE        SIGNATURE_32 ('$', 'V', 'S', 'D')

+#define DEV_FROM_THIS(a)        CR (a, VS_DEV, VarStore, VS_DEV_SIGNATURE)

+

+#define VAR_DATA_PTR(a)         ((a)->Info.Data)

+#define VAR_FILE_DEVICEPATH(a)  ((a)->Info.FileInfo.DevicePath)

+#define VAR_FILE_VOLUMEID(a)    ((a)->Info.FileInfo.VolumeId)

+#define VAR_FILE_FILEPATH(a)    ((a)->Info.FileInfo.FilePath)

+

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/DUETFwh.inf b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/DUETFwh.inf
new file mode 100644
index 0000000..050b80a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/DUETFwh.inf
@@ -0,0 +1,58 @@
+## @file

+#

+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+# 

+#  Module Name:

+#

+#   DUETFwh.inf

+#

+#  Abstract:

+#

+#    Component description file for DUET Module

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = DuetFwh

+  FILE_GUID                      = 46E3256A-E5C1-4d2a-8282-505AFB41CE65

+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = FvbInitialize

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[Sources]

+  FWBlockService.c

+  FwBlockService.h

+  FvbInfo.c

+  FileIo.c

+  FileIo.h

+

+[LibraryClasses]

+  DevicePathLib

+  UefiLib

+  UefiDriverEntryPoint

+  UefiRuntimeLib

+  HobLib

+

+[Guids]

+  gEfiFlashMapHobGuid

+

+[Protocols]

+  gEfiSimpleFileSystemProtocolGuid

+  gEfiFirmwareVolumeBlockProtocolGuid

+  gEfiBlockIoProtocolGuid

+

+[Depex]

+  TRUE

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FWBlockService.c b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FWBlockService.c
new file mode 100644
index 0000000..e0ddbd5
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FWBlockService.c
@@ -0,0 +1,1659 @@
+/**@file

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FWBlockService.c

+    

+Abstract:

+

+Revision History

+

+**/

+#include "FWBlockService.h"

+#include "EfiFlashMap.h"

+#include "FileIo.h"

+#include "FlashLayout.h"

+

+ESAL_FWB_GLOBAL       *mFvbModuleGlobal;

+VOID                  *mSFSRegistration;

+#define TRY_ASSIGN(var, value)  if(var != NULL) {*var = value;}

+

+EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {

+  FVB_DEVICE_SIGNATURE,

+  {

+    {

+      {

+        HARDWARE_DEVICE_PATH,

+        HW_MEMMAP_DP,

+        {

+          sizeof (MEMMAP_DEVICE_PATH),

+          0

+        }

+      },

+      EfiMemoryMappedIO,

+      0,

+      0,

+    },

+    {

+      END_DEVICE_PATH_TYPE,

+      END_ENTIRE_DEVICE_PATH_SUBTYPE,

+      {

+        sizeof (EFI_DEVICE_PATH_PROTOCOL),

+        0

+      }

+    }

+  },

+  0,

+  {

+    FvbProtocolGetAttributes,

+    FvbProtocolSetAttributes,

+    FvbProtocolGetPhysicalAddress,

+    FvbProtocolGetBlockSize,

+    FvbProtocolRead,

+    FvbProtocolWrite,

+    FvbProtocolEraseBlocks,

+    NULL

+  }

+};

+

+

+EFI_STATUS

+FlashFdWrite (

+  IN     UINTN                            Address,

+  IN     EFI_FW_VOL_INSTANCE              *FwhInstance,

+  IN OUT UINTN                            *NumBytes,

+  IN     UINT8                            *Buffer

+  )

+/*++

+

+Routine Description:

+  Writes specified number of bytes from the input buffer to the address

+

+Arguments:

+

+Returns: 

+

+--*/

+{

+  EFI_STATUS          Status;

+  EFI_FILE_PROTOCOL   *File;

+  UINTN               FileOffset;

+  UINTN               BufferForFile;

+  UINTN               Length;

+

+  Status = EFI_SUCCESS;

+  CopyMem ((VOID *) Address, Buffer, *NumBytes);

+

+  if (!EfiAtRuntime () && (FwhInstance->Device != NULL)) {

+    Status = FileOpen (FwhInstance->Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE);

+    ASSERT_EFI_ERROR (Status);

+    if (!EFI_ERROR (Status)) {

+      if (Address - FwhInstance->FvBase[FVB_PHYSICAL] < FwhInstance->Offset) {

+        FileOffset = 0;

+        BufferForFile = FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset;

+        Length = *NumBytes - (FwhInstance->Offset - (Address - FwhInstance->FvBase[FVB_PHYSICAL]));

+      } else {

+        FileOffset = Address - FwhInstance->FvBase[FVB_PHYSICAL] - FwhInstance->Offset;

+        BufferForFile = Address;

+        Length = *NumBytes;

+      }

+      

+      Status = FileWrite (File, FileOffset, BufferForFile, Length);

+      ASSERT_EFI_ERROR (Status);

+      FileClose (File);

+    }

+  }

+  return Status;

+}

+

+EFI_STATUS

+FlashFdErase (

+  IN UINTN                                Address,

+  IN EFI_FW_VOL_INSTANCE                  *FwhInstance,

+  IN UINTN                                LbaLength

+  )

+/*++

+

+Routine Description:

+  Erase a certain block from address LbaWriteAddress

+

+Arguments:

+

+Returns: 

+

+--*/

+{

+  EFI_STATUS           Status;

+  EFI_FILE_PROTOCOL    *File;

+  UINTN                FileOffset;

+  UINTN                BufferForFile;

+  UINTN                Length;

+

+  Status = EFI_SUCCESS;

+

+  SetMem ((VOID *)Address, LbaLength, 0xff);

+

+  if (!EfiAtRuntime () && (FwhInstance->Device != NULL)) {

+    Status = FileOpen (FwhInstance->Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE);

+    ASSERT_EFI_ERROR (Status);

+    if (!EFI_ERROR (Status)) {

+      if (Address - FwhInstance->FvBase[FVB_PHYSICAL] < FwhInstance->Offset) {

+        FileOffset = 0;

+        BufferForFile = FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset;

+        Length = LbaLength - (FwhInstance->Offset - (Address - FwhInstance->FvBase[FVB_PHYSICAL]));

+      } else {

+        FileOffset = Address - FwhInstance->FvBase[FVB_PHYSICAL] - FwhInstance->Offset;

+        BufferForFile = Address;

+        Length = LbaLength;

+      }

+      

+      Status = FileWrite (File, FileOffset, BufferForFile, Length);

+      ASSERT_EFI_ERROR (Status);

+      FileClose (File);

+    }

+  }

+  return Status;

+}

+

+VOID

+EFIAPI

+FvbVirtualddressChangeEvent (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  )

+/*++

+

+Routine Description:

+

+  Fixup internal data so that EFI and SAL can be call in virtual mode.

+  Call the passed in Child Notify event and convert the mFvbModuleGlobal

+  date items to there virtual address.

+

+  mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]  - Physical copy of instance data

+  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]   - Virtual pointer to common 

+                                                instance data.

+

+Arguments:

+

+  (Standard EFI notify event - EFI_EVENT_NOTIFY)

+

+Returns: 

+

+  None

+

+--*/

+{

+  EFI_FW_VOL_INSTANCE *FwhInstance;

+  UINTN               Index;

+

+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);

+

+  //

+  // Convert the base address of all the instances

+  //

+  Index       = 0;

+  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];

+  while (Index < mFvbModuleGlobal->NumFv) {

+    EfiConvertPointer (0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);

+    FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + FwhInstance->VolumeHeader.HeaderLength

+                    + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));

+    Index++;

+  }

+

+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);

+  EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal);

+}

+

+EFI_STATUS

+GetFvbInstance (

+  IN  UINTN                               Instance,

+  IN  ESAL_FWB_GLOBAL                     *Global,

+  OUT EFI_FW_VOL_INSTANCE                 **FwhInstance,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Retrieves the physical address of a memory mapped FV

+

+Arguments:

+  Instance              - The FV instance whose base address is going to be

+                          returned

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  FwhInstance           - The EFI_FW_VOL_INSTANCE fimrware instance structure

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+  EFI_INVALID_PARAMETER - Instance not found

+

+--*/

+{

+  EFI_FW_VOL_INSTANCE *FwhRecord;

+

+  if (Instance >= Global->NumFv) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Find the right instance of the FVB private data

+  //

+  FwhRecord = Global->FvInstance[Virtual];

+  while (Instance > 0) {

+    FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength 

+                     + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));

+    Instance--;

+  }

+

+  *FwhInstance = FwhRecord;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+FvbGetPhysicalAddress (

+  IN UINTN                                Instance,

+  OUT EFI_PHYSICAL_ADDRESS                *Address,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Retrieves the physical address of a memory mapped FV

+

+Arguments:

+  Instance              - The FV instance whose base address is going to be

+                          returned

+  Address               - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 

+                          that on successful return, contains the base address

+                          of the firmware volume. 

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+  EFI_INVALID_PARAMETER - Instance not found

+

+--*/

+{

+  EFI_FW_VOL_INSTANCE *FwhInstance;

+  EFI_STATUS          Status;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+  *Address = FwhInstance->FvBase[Virtual];

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+FvbGetVolumeAttributes (

+  IN UINTN                                Instance,

+  OUT EFI_FVB_ATTRIBUTES_2                *Attributes,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Retrieves attributes, insures positive polarity of attribute bits, returns

+  resulting attributes in output parameter

+

+Arguments:

+  Instance              - The FV instance whose attributes is going to be 

+                          returned

+  Attributes            - Output buffer which contains attributes

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+  EFI_INVALID_PARAMETER - Instance not found

+

+--*/

+{

+  EFI_FW_VOL_INSTANCE *FwhInstance;

+  EFI_STATUS          Status;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+  *Attributes = FwhInstance->VolumeHeader.Attributes;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+FvbGetLbaAddress (

+  IN  UINTN                               Instance,

+  IN  EFI_LBA                             Lba,

+  OUT UINTN                               *LbaAddress  OPTIONAL,

+  OUT UINTN                               *LbaLength   OPTIONAL,

+  OUT UINTN                               *NumOfBlocks OPTIONAL,

+  IN  ESAL_FWB_GLOBAL                     *Global,

+  IN  BOOLEAN                             Virtual

+  )

+/*++

+

+Routine Description:

+  Retrieves the starting address of an LBA in an FV

+

+Arguments:

+  Instance              - The FV instance which the Lba belongs to

+  Lba                   - The logical block address

+  LbaAddress            - On output, contains the physical starting address

+                          of the Lba for writing

+  LbaLength             - On output, contains the length of the block

+  NumOfBlocks           - A pointer to a caller allocated UINTN in which the

+                          number of consecutive blocks starting with Lba is

+                          returned. All blocks in this range have a size of

+                          BlockSize

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+  EFI_INVALID_PARAMETER - Instance not found

+

+--*/

+{

+  UINT32                  NumBlocks;

+  UINT32                  BlockLength;

+  UINTN                   Offset;

+  EFI_LBA                 StartLba;

+  EFI_LBA                 NextLba;

+  EFI_FW_VOL_INSTANCE     *FwhInstance;

+  EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;

+  EFI_STATUS              Status;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+

+  StartLba  = 0;

+  Offset    = 0;

+  BlockMap  = &(FwhInstance->VolumeHeader.BlockMap[0]);

+

+  //

+  // Parse the blockmap of the FV to find which map entry the Lba belongs to

+  //

+  while (TRUE) {

+    NumBlocks   = BlockMap->NumBlocks;

+    BlockLength = BlockMap->Length;

+

+    if (NumBlocks == 0 || BlockLength == 0) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    NextLba = StartLba + NumBlocks;

+

+    //

+    // The map entry found

+    //

+    if (Lba >= StartLba && Lba < NextLba) {

+      Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);

+

+      if (LbaAddress) {

+        *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;

+      }

+

+      if (LbaLength) {

+        *LbaLength = BlockLength;

+      }

+

+      if (NumOfBlocks) {

+        *NumOfBlocks = (UINTN) (NextLba - Lba);

+      }

+

+      return EFI_SUCCESS;

+    }

+

+    StartLba  = NextLba;

+    Offset    = Offset + NumBlocks * BlockLength;

+    BlockMap++;

+  }

+}

+

+EFI_STATUS

+FvbReadBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN UINTN                                BlockOffset,

+  IN OUT UINTN                            *NumBytes,

+  IN UINT8                                *Buffer,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Reads specified number of bytes into a buffer from the specified block

+

+Arguments:

+  Instance              - The FV instance to be read from

+  Lba                   - The logical block address to be read from

+  BlockOffset           - Offset into the block at which to begin reading

+  NumBytes              - Pointer that on input contains the total size of

+                          the buffer. On output, it contains the total number

+                          of bytes read

+  Buffer                - Pointer to a caller allocated buffer that will be

+                          used to hold the data read

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume was read successfully and 

+                          contents are in Buffer

+  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,

+                          NumBytes contains the total number of bytes returned

+                          in Buffer

+  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be read

+  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL

+

+--*/

+{

+  EFI_FVB_ATTRIBUTES_2  Attributes;

+  UINTN                 LbaAddress;

+  UINTN                 LbaLength;

+  EFI_STATUS            Status;

+

+  //

+  // Check for invalid conditions

+  //

+  if ((NumBytes == NULL) || (Buffer == NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (*NumBytes == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Check if the FV is read enabled

+  //

+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);

+

+  if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {

+    return EFI_ACCESS_DENIED;

+  }

+  //

+  // Perform boundary checks and adjust NumBytes

+  //

+  if (BlockOffset > LbaLength) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (LbaLength < (*NumBytes + BlockOffset)) {

+    *NumBytes = (UINT32) (LbaLength - BlockOffset);

+    Status    = EFI_BAD_BUFFER_SIZE;

+  }

+

+  CopyMem (Buffer, (VOID *) (LbaAddress + BlockOffset), (UINTN) *NumBytes);

+

+  return Status;

+}

+EFI_STATUS

+FvbWriteBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN UINTN                                BlockOffset,

+  IN OUT UINTN                            *NumBytes,

+  IN UINT8                                *Buffer,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Writes specified number of bytes from the input buffer to the block

+

+Arguments:

+  Instance              - The FV instance to be written to

+  Lba                   - The starting logical block index to write to

+  BlockOffset           - Offset into the block at which to begin writing

+  NumBytes              - Pointer that on input contains the total size of

+                          the buffer. On output, it contains the total number

+                          of bytes actually written

+  Buffer                - Pointer to a caller allocated buffer that contains

+                          the source for the write

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume was written successfully

+  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,

+                          NumBytes contains the total number of bytes

+                          actually written

+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be written

+  EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL

+

+--*/

+{

+  EFI_FVB_ATTRIBUTES_2  Attributes;

+  UINTN                 LbaAddress;

+  UINTN                 LbaLength;

+  EFI_FW_VOL_INSTANCE   *FwhInstance;

+  EFI_STATUS            Status;

+  EFI_STATUS            ReturnStatus;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Writes are enabled in the init routine itself

+  //

+  if (!FwhInstance->WriteEnabled) {

+    return EFI_ACCESS_DENIED;

+  }

+  //

+  // Check for invalid conditions

+  //

+  if ((NumBytes == NULL) || (Buffer == NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (*NumBytes == 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Check if the FV is write enabled

+  //

+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);

+

+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {

+    return EFI_ACCESS_DENIED;

+  }

+  //

+  // Perform boundary checks and adjust NumBytes

+  //

+  if (BlockOffset > LbaLength) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (LbaLength < (*NumBytes + BlockOffset)) {

+    *NumBytes = (UINT32) (LbaLength - BlockOffset);

+    Status    = EFI_BAD_BUFFER_SIZE;

+  }

+

+  ReturnStatus = FlashFdWrite (

+                  LbaAddress + BlockOffset,

+                  FwhInstance,

+                  NumBytes,

+                  Buffer

+                  );

+  if (EFI_ERROR (ReturnStatus)) {

+    return ReturnStatus;

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+FvbEraseBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Erases and initializes a firmware volume block

+

+Arguments:

+  Instance              - The FV instance to be erased

+  Lba                   - The logical block index to be erased

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - The erase request was successfully completed

+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be written. Firmware device may have been

+                          partially erased

+  EFI_INVALID_PARAMETER - Instance not found

+

+--*/

+{

+

+  EFI_FVB_ATTRIBUTES_2  Attributes;

+  UINTN                 LbaAddress;

+  EFI_FW_VOL_INSTANCE   *FwhInstance;

+  UINTN                 LbaLength;

+  EFI_STATUS            Status;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Writes are enabled in the init routine itself

+  //

+  if (!FwhInstance->WriteEnabled) {

+    return EFI_ACCESS_DENIED;

+  }

+  //

+  // Check if the FV is write enabled

+  //

+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);

+

+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {

+    return EFI_ACCESS_DENIED;

+  }

+  //

+  // Get the starting address of the block for erase. For debug reasons,

+  // LbaWriteAddress may not be the same as LbaAddress.

+  //

+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return FlashFdErase (

+          LbaAddress,

+          FwhInstance,

+          LbaLength

+          );

+}

+

+EFI_STATUS

+FvbSetVolumeAttributes (

+  IN UINTN                                Instance,

+  IN OUT EFI_FVB_ATTRIBUTES_2             *Attributes,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  )

+/*++

+

+Routine Description:

+  Modifies the current settings of the firmware volume according to the 

+  input parameter, and returns the new setting of the volume

+

+Arguments:

+  Instance              - The FV instance whose attributes is going to be 

+                          modified

+  Attributes            - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 

+                          containing the desired firmware volume settings.

+                          On successful return, it contains the new settings

+                          of the firmware volume

+  Global                - Pointer to ESAL_FWB_GLOBAL that contains all

+                          instance data

+  Virtual               - Whether CPU is in virtual or physical mode

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+  EFI_ACCESS_DENIED     - The volume setting is locked and cannot be modified

+  EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are

+                          in conflict with the capabilities as declared in the

+                          firmware volume header

+

+--*/

+{

+  EFI_FW_VOL_INSTANCE   *FwhInstance;

+  EFI_FVB_ATTRIBUTES_2  OldAttributes;

+  EFI_FVB_ATTRIBUTES_2  *AttribPtr;

+  UINT32                Capabilities;

+  UINT32                OldStatus;

+  UINT32                NewStatus;

+  EFI_STATUS            Status;

+

+  //

+  // Find the right instance of the FVB private data

+  //

+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);

+  ASSERT_EFI_ERROR (Status);

+

+  AttribPtr     = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);

+  OldAttributes = *AttribPtr;

+  Capabilities  = OldAttributes & EFI_FVB2_CAPABILITIES;

+  OldStatus     = OldAttributes & EFI_FVB2_STATUS;

+  NewStatus     = *Attributes & EFI_FVB2_STATUS;

+

+  //

+  // If firmware volume is locked, no status bit can be updated

+  //

+  if (OldAttributes & EFI_FVB2_LOCK_STATUS) {

+    if (OldStatus ^ NewStatus) {

+      return EFI_ACCESS_DENIED;

+    }

+  }

+  //

+  // Test read disable

+  //

+  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {

+    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Test read enable

+  //

+  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {

+    if (NewStatus & EFI_FVB2_READ_STATUS) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Test write disable

+  //

+  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {

+    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Test write enable

+  //

+  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {

+    if (NewStatus & EFI_FVB2_WRITE_STATUS) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+  //

+  // Test lock

+  //

+  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {

+    if (NewStatus & EFI_FVB2_LOCK_STATUS) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+

+  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));

+  *AttribPtr  = (*AttribPtr) | NewStatus;

+  *Attributes = *AttribPtr;

+

+  return EFI_SUCCESS;

+}

+//

+// FVB protocol APIs

+//

+EFI_STATUS

+EFIAPI

+FvbProtocolGetPhysicalAddress (

+  IN  CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,

+  OUT       EFI_PHYSICAL_ADDRESS                        *Address

+  )

+/*++

+

+Routine Description:

+

+  Retrieves the physical address of the device.

+

+Arguments:

+

+  This                  - Calling context

+  Address               - Output buffer containing the address.

+

+Returns:

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+

+--*/

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetBlockSize (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL           *This,

+  IN  EFI_LBA                                     Lba,

+  OUT UINTN                                       *BlockSize,

+  OUT UINTN                                       *NumOfBlocks

+  )

+/*++

+

+Routine Description:

+  Retrieve the size of a logical block

+

+Arguments:

+  This                  - Calling context

+  Lba                   - Indicates which block to return the size for.

+  BlockSize             - A pointer to a caller allocated UINTN in which

+                          the size of the block is returned

+  NumOfBlocks           - a pointer to a caller allocated UINTN in which the

+                          number of consecutive blocks starting with Lba is

+                          returned. All blocks in this range have a size of

+                          BlockSize

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume was read successfully and 

+                          contents are in Buffer

+

+--*/

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbGetLbaAddress (

+          FvbDevice->Instance,

+          Lba,

+          NULL,

+          BlockSize,

+          NumOfBlocks,

+          mFvbModuleGlobal,

+          EfiGoneVirtual ()

+          );

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetAttributes (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,

+  OUT      EFI_FVB_ATTRIBUTES_2                        *Attributes

+  )

+/*++

+

+Routine Description:

+    Retrieves Volume attributes.  No polarity translations are done.

+

+Arguments:

+    This                - Calling context

+    Attributes          - output buffer which contains attributes

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+

+--*/

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolSetAttributes (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,

+  IN OUT   EFI_FVB_ATTRIBUTES_2                     *Attributes

+  )

+/*++

+

+Routine Description:

+  Sets Volume attributes. No polarity translations are done.

+

+Arguments:

+  This                  - Calling context

+  Attributes            - output buffer which contains attributes

+

+Returns: 

+  EFI_SUCCESS           - Successfully returns

+

+--*/

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolEraseBlocks (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,

+  ...  

+  )

+/*++

+

+Routine Description:

+

+  The EraseBlock() function erases one or more blocks as denoted by the 

+  variable argument list. The entire parameter list of blocks must be verified

+  prior to erasing any blocks.  If a block is requested that does not exist 

+  within the associated firmware volume (it has a larger index than the last 

+  block of the firmware volume), the EraseBlock() function must return

+  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.

+

+Arguments:

+  This                  - Calling context

+  ...                   - Starting LBA followed by Number of Lba to erase. 

+                          a -1 to terminate the list.

+

+Returns: 

+  EFI_SUCCESS           - The erase request was successfully completed

+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be written. Firmware device may have been

+                          partially erased

+

+--*/

+{

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+  EFI_FW_VOL_INSTANCE     *FwhInstance;

+  UINTN                   NumOfBlocks;

+  VA_LIST                 args;

+  EFI_LBA                 StartingLba;

+  UINTN                   NumOfLba;

+  EFI_STATUS              Status;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  Status    = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());

+  ASSERT_EFI_ERROR (Status);

+

+  NumOfBlocks = FwhInstance->NumOfBlocks;

+

+  VA_START (args, This);

+

+  do {

+    StartingLba = VA_ARG (args, EFI_LBA);

+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {

+      break;

+    }

+

+    NumOfLba = VA_ARG (args, UINT32);

+

+    //

+    // Check input parameters

+    //

+    if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {

+      VA_END (args);

+      return EFI_INVALID_PARAMETER;

+    }

+  } while (1);

+

+  VA_END (args);

+

+  VA_START (args, This);

+  do {

+    StartingLba = VA_ARG (args, EFI_LBA);

+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {

+      break;

+    }

+

+    NumOfLba = VA_ARG (args, UINT32);

+

+    while (NumOfLba > 0) {

+      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());

+      if (EFI_ERROR (Status)) {

+        VA_END (args);

+        return Status;

+      }

+

+      StartingLba++;

+      NumOfLba--;

+    }

+

+  } while (1);

+

+  VA_END (args);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolWrite (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,

+  IN EFI_LBA                                      Lba,

+  IN UINTN                                        Offset,

+  IN OUT UINTN                                    *NumBytes,

+  IN UINT8                                        *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Writes data beginning at Lba:Offset from FV. The write terminates either

+  when *NumBytes of data have been written, or when a block boundary is

+  reached.  *NumBytes is updated to reflect the actual number of bytes

+  written. The write opertion does not include erase. This routine will

+  attempt to write only the specified bytes. If the writes do not stick,

+  it will return an error.

+

+Arguments:

+  This                  - Calling context

+  Lba                   - Block in which to begin write

+  Offset                - Offset in the block at which to begin write

+  NumBytes              - On input, indicates the requested write size. On

+                          output, indicates the actual number of bytes written

+  Buffer                - Buffer containing source data for the write.

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume was written successfully

+  EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,

+                          NumBytes contains the total number of bytes

+                          actually written

+  EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be written

+  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL

+

+--*/

+{

+

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());

+}

+

+EFI_STATUS

+EFIAPI

+FvbProtocolRead (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,

+  IN EFI_LBA                                      Lba,

+  IN UINTN                                        Offset,

+  IN OUT UINTN                                    *NumBytes,

+  IN UINT8                                        *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Reads data beginning at Lba:Offset from FV. The Read terminates either

+  when *NumBytes of data have been read, or when a block boundary is

+  reached.  *NumBytes is updated to reflect the actual number of bytes

+  written. The write opertion does not include erase. This routine will

+  attempt to write only the specified bytes. If the writes do not stick,

+  it will return an error.

+

+Arguments:

+  This                  - Calling context

+  Lba                   - Block in which to begin Read

+  Offset                - Offset in the block at which to begin Read

+  NumBytes              - On input, indicates the requested write size. On

+                          output, indicates the actual number of bytes Read

+  Buffer                - Buffer containing source data for the Read.

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume was read successfully and 

+                          contents are in Buffer

+  EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,

+                          NumBytes contains the total number of bytes returned

+                          in Buffer

+  EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state

+  EFI_DEVICE_ERROR      - The block device is not functioning correctly and 

+                          could not be read

+  EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL

+

+--*/

+{

+

+  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

+

+  FvbDevice = FVB_DEVICE_FROM_THIS (This);

+

+  return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());

+}

+

+EFI_STATUS

+ValidateFvHeader (

+  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader

+  )

+/*++

+

+Routine Description:

+  Check the integrity of firmware volume header

+

+Arguments:

+  FwVolHeader           - A pointer to a firmware volume header

+

+Returns: 

+  EFI_SUCCESS           - The firmware volume is consistent

+  EFI_NOT_FOUND         - The firmware volume has corrupted. So it is not an FV

+

+--*/

+{

+  UINT16  *Ptr;

+  UINT16  HeaderLength;

+  UINT16  Checksum;

+

+  //

+  // Verify the header revision, header signature, length

+  // Length of FvBlock cannot be 2**64-1

+  // HeaderLength cannot be an odd number

+  //

+  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||

+      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||

+      (FwVolHeader->FvLength == ((UINTN) -1)) ||

+      ((FwVolHeader->HeaderLength & 0x01) != 0)

+      ) {

+    return EFI_NOT_FOUND;

+  }

+  //

+  // Verify the header checksum

+  //

+  HeaderLength  = (UINT16) (FwVolHeader->HeaderLength / 2);

+  Ptr           = (UINT16 *) FwVolHeader;

+  Checksum      = 0;

+  while (HeaderLength > 0) {

+    Checksum = Checksum + (*Ptr);

+    HeaderLength--;

+    Ptr++;

+  }

+

+  if (Checksum != 0) {

+    return EFI_NOT_FOUND;

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+EFI_STATUS

+GetFvbHeader (

+  IN OUT EFI_PEI_HOB_POINTERS           *HobList,

+  OUT    EFI_FIRMWARE_VOLUME_HEADER     **FwVolHeader,

+  OUT    EFI_PHYSICAL_ADDRESS           *BaseAddress     OPTIONAL,

+  OUT    UINT32                         *VolumeId        OPTIONAL,

+  OUT    CHAR16                         **MappedFile     OPTIONAL,

+  OUT    UINT32                         *ActuralSize     OPTIONAL,

+  OUT    UINT32                         *Offset          OPTIONAL,

+  OUT    BOOLEAN                        *WriteBack       OPTIONAL

+  )

+{

+  EFI_STATUS                  Status;

+  EFI_FLASH_MAP_FS_ENTRY_DATA *FlashMapEntry;

+  EFI_FLASH_SUBAREA_ENTRY     *FlashMapSubEntry;

+

+  Status        = EFI_SUCCESS;

+  *FwVolHeader  = NULL;

+  TRY_ASSIGN (WriteBack, FALSE);

+

+  DEBUG ((EFI_D_INFO, "Hob start is 0x%x\n", (UINTN)(*HobList).Raw));

+  (*HobList).Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, (*HobList).Raw);

+  if ((*HobList).Raw == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  FlashMapEntry     = (EFI_FLASH_MAP_FS_ENTRY_DATA *) GET_GUID_HOB_DATA ((*HobList).Guid);

+  FlashMapSubEntry  = &FlashMapEntry->Entries[0];

+  

+  //

+  // Check if it is a "FVB" area

+  //

+  if (!CompareGuid (&FlashMapSubEntry->FileSystem, &gEfiFirmwareVolumeBlockProtocolGuid)) {

+    return Status;

+  }

+  //

+  // Check if it is a "real" flash

+  //

+  if (FlashMapSubEntry->Attributes != (EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV)) {

+    return Status;

+  }

+

+  TRY_ASSIGN (BaseAddress, FlashMapSubEntry->Base);

+

+  //

+  // Cast buffer to FLASH_AREA_INFO to get extra information related to the special FVB driver

+  //

+  TRY_ASSIGN (VolumeId,    FlashMapEntry->VolumeId);

+  TRY_ASSIGN (ActuralSize, FlashMapEntry->ActuralSize);

+  TRY_ASSIGN (MappedFile, ((CHAR16 *) FlashMapEntry->FilePath));

+  TRY_ASSIGN (Offset,      FlashMapEntry->Offset);

+

+  DEBUG ((

+    EFI_D_INFO, 

+    "FlashMap HOB: BaseAddress = 0x%x, Length = 0x%x, ActuralLength = 0x%x, Offset = 0x%x\n", 

+    (UINTN) FlashMapSubEntry->Base, (UINTN) FlashMapSubEntry->Length, 

+    (UINTN) FlashMapEntry->ActuralSize, (UINTN) FlashMapEntry->Offset

+  ));

+  DEBUG ((

+    EFI_D_INFO,

+    "FlashMap HOB: VolumeId = 0x%lx, MappedFile = %s\n",

+    (UINTN) FlashMapEntry->VolumeId, (UINTN) FlashMapEntry->FilePath

+  ));

+  *FwVolHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (FlashMapSubEntry->Base);

+  Status        = ValidateFvHeader (*FwVolHeader);

+  if (EFI_ERROR (Status)) {

+    //

+    // Get FvbInfo

+    //

+    TRY_ASSIGN (WriteBack, TRUE);

+    Status = GetFvbInfo (FlashMapSubEntry->Length, FwVolHeader);

+    DEBUG ((EFI_D_ERROR, "Fvb: FV header invalid, GetFvbInfo - %r\n", Status));

+    ASSERT_EFI_ERROR (Status);

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+EFIAPI

+OnSimpleFileSystemInstall (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  )

+{

+  EFI_STATUS                Status;

+  UINTN                     HandleSize;

+  EFI_HANDLE                Handle;

+  UINTN                     Instance;

+  EFI_DEVICE_PATH_PROTOCOL  *Device;

+  EFI_FILE_PROTOCOL         *File;

+  EFI_FW_VOL_INSTANCE       *FwhInstance;

+  while (TRUE) {

+    HandleSize = sizeof (EFI_HANDLE);

+    Status = gBS->LocateHandle (

+                    ByRegisterNotify,

+                    NULL,

+                    mSFSRegistration,

+                    &HandleSize,

+                    &Handle

+                    );

+    if (Status == EFI_NOT_FOUND) {

+      break;

+    }

+    DEBUG ((EFI_D_ERROR, "Fwh: New FileSystem Installed!\n"));

+    ASSERT_EFI_ERROR (Status);

+    //

+    // Check if this is the storage we care about, and store it in FwhInstance

+    //

+    for (Instance = 0; Instance < mFvbModuleGlobal->NumFv; ++Instance) {

+      Status = GetFvbInstance (Instance, mFvbModuleGlobal, &FwhInstance, FALSE);

+      ASSERT_EFI_ERROR (Status);

+

+      if (FwhInstance->MappedFile[0] == L'\0') {

+        //

+        // The instance of FVB isn't mapped to file.

+        //

+        continue;

+      }

+

+      if ((FwhInstance->Device != NULL) && 

+          !EFI_ERROR (CheckStoreExists (FwhInstance->Device))

+          ) {

+        //

+        // The instance of FVB has already associated to a device

+        //  and the device is not removed from system.

+        //

+        DEBUG ((

+              EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Already mapped, Skip!\n", 

+              (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],

+              (UINTN) FwhInstance->Offset

+              ));

+        continue;

+      }

+

+      Status = CheckStore (Handle, FwhInstance->VolumeId, &Device);

+      if (!EFI_ERROR (Status)) {

+        //

+        // Write back memory content to file

+        //

+        Status = FileOpen (Device, FwhInstance->MappedFile, &File, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE);

+        ASSERT_EFI_ERROR (Status); 

+        if (!EFI_ERROR (Status)) {

+          DEBUG ((

+                EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Write back to mapped file!\n", 

+                (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],

+                (UINTN) FwhInstance->Offset

+                ));

+          Status = FileWrite (

+                     File, 

+                     0, 

+                     FwhInstance->FvBase[FVB_PHYSICAL] + FwhInstance->Offset, 

+                     FwhInstance->ActuralSize - FwhInstance->Offset

+                     );

+          ASSERT_EFI_ERROR (Status); 

+          if (!EFI_ERROR (Status)) {

+            if (FwhInstance->Device != NULL) {

+              gBS->FreePool (FwhInstance->Device);

+            }

+            FwhInstance->Device = Device;

+            DEBUG ((

+                  EFI_D_ERROR, "Fwh: MappedFile FVB (0x%x:0x%x) - Mapped!\n",

+                  (UINTN) FwhInstance->FvBase[FVB_PHYSICAL],

+                  (UINTN) FwhInstance->Offset

+                  ));

+          }

+          FileClose (File);

+        }

+      }

+    }

+  }

+}

+

+VOID

+FvbInstallSfsNotify (

+  VOID

+)

+{

+  EFI_STATUS Status;

+  EFI_EVENT  Event;

+

+  Status = gBS->CreateEvent (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  OnSimpleFileSystemInstall,

+                  NULL,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->RegisterProtocolNotify (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  Event,

+                  &mSFSRegistration

+                  );

+  ASSERT_EFI_ERROR (Status);

+}

+

+

+EFI_STATUS

+EFIAPI

+FvbInitialize (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+/*++

+

+Routine Description:

+  This function does common initialization for FVB services

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  EFI_STATUS                          Status;

+  EFI_FW_VOL_INSTANCE                 *FwhInstance;

+  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;

+  EFI_PEI_HOB_POINTERS                FirmwareVolumeHobList;

+  UINT32                              BufferSize;

+  EFI_FV_BLOCK_MAP_ENTRY              *PtrBlockMapEntry;

+  UINTN                               LbaAddress;

+  EFI_HANDLE                          FwbHandle;

+  EFI_FW_VOL_BLOCK_DEVICE             *FvbDevice;

+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *OldFwbInterface;

+  EFI_DEVICE_PATH_PROTOCOL            *TempFwbDevicePath;

+  FV_DEVICE_PATH                      TempFvbDevicePathData;

+  UINT32                              MaxLbaSize;

+  EFI_PHYSICAL_ADDRESS                BaseAddress;

+  UINT32                              VolumeId;

+  CHAR16                              *MappedFile;

+  UINT32                              ActuralSize;

+  UINT32                              Offset;

+  BOOLEAN                             WriteBack;

+  UINTN                               NumOfBlocks;

+  UINTN                               HeaderLength;

+  BOOLEAN                             InstallSfsNotify;

+

+  HeaderLength     = 0;

+  InstallSfsNotify = FALSE;

+

+  //

+  // Allocate runtime services data for global variable, which contains

+  // the private data of all firmware volume block instances

+  //

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  sizeof (ESAL_FWB_GLOBAL),

+                  &mFvbModuleGlobal

+                  );

+  ASSERT_EFI_ERROR (Status);

+  //

+  // Calculate the total size for all firmware volume block instances

+  //

+  BufferSize            = 0;

+  FirmwareVolumeHobList.Raw = GetHobList();

+  do {

+    Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, NULL, NULL, NULL, NULL, NULL, NULL);

+    if (EFI_ERROR (Status)) {

+      break;

+    }

+    FirmwareVolumeHobList.Raw = GET_NEXT_HOB (FirmwareVolumeHobList);

+

+    if (FwVolHeader) {

+      BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER));

+    }

+  } while (TRUE);

+

+  //

+  // Only need to allocate once. There is only one copy of physical memory for

+  // the private data of each FV instance. But in virtual mode or in physical

+  // mode, the address of the the physical memory may be different.

+  //

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  BufferSize,

+                  &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Make a virtual copy of the FvInstance pointer.

+  //

+  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];

+  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;

+

+  mFvbModuleGlobal->NumFv     = 0;

+  FirmwareVolumeHobList.Raw   = GetHobList();

+  MaxLbaSize                  = 0;

+

+  //

+  // Fill in the private data of each firmware volume block instance

+  //

+  do {

+    Status = GetFvbHeader (

+               &FirmwareVolumeHobList, &FwVolHeader, 

+               &BaseAddress, &VolumeId, &MappedFile, &ActuralSize, &Offset,

+               &WriteBack

+             );

+    if (EFI_ERROR (Status)) {

+      break;

+    }

+    FirmwareVolumeHobList.Raw = GET_NEXT_HOB (FirmwareVolumeHobList);

+

+    if (!FwVolHeader) {

+      continue;

+    }

+    

+    CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);

+    FwVolHeader                       = &(FwhInstance->VolumeHeader);

+

+    FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;

+    FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN) BaseAddress;

+    FwhInstance->Device               = NULL;

+    FwhInstance->Offset               = Offset;

+

+    if (*MappedFile != '\0') {

+      FwhInstance->VolumeId             = VolumeId;

+      FwhInstance->ActuralSize          = ActuralSize;

+      StrCpy (FwhInstance->MappedFile, MappedFile);

+

+      InstallSfsNotify = TRUE;

+    } else {

+      FwhInstance->VolumeId             = (UINT32) -1;

+      FwhInstance->ActuralSize          = (UINT32) -1;

+      FwhInstance->MappedFile[0]        = L'\0';

+    }

+    

+    DEBUG ((EFI_D_INFO, "FirmVolume Found! BaseAddress=0x%lx, VolumeId=0x%x, MappedFile=%s, Size=0x%x\n",

+           (UINTN) BaseAddress, VolumeId, MappedFile, ActuralSize));

+    //

+    // We may expose readonly FVB in future.

+    //

+    FwhInstance->WriteEnabled         = TRUE; // Ken: Why enable write?

+    EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);

+

+    LbaAddress  = (UINTN) FwhInstance->FvBase[0];

+    NumOfBlocks = 0;

+

+    if (FwhInstance->WriteEnabled) {

+      for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {

+

+        LbaAddress += PtrBlockMapEntry->NumBlocks * PtrBlockMapEntry->Length;

+        //

+        // Get the maximum size of a block. The size will be used to allocate

+        // buffer for Scratch space, the intermediate buffer for FVB extension

+        // protocol

+        //

+        if (MaxLbaSize < PtrBlockMapEntry->Length) {

+          MaxLbaSize = PtrBlockMapEntry->Length;

+        }

+

+        NumOfBlocks += PtrBlockMapEntry->NumBlocks;

+      }

+      //

+      //  Write back a healthy FV header

+      //

+      if (WriteBack) {

+        Status = FlashFdErase (

+                  (UINTN) FwhInstance->FvBase[0],

+                  FwhInstance,

+                  FwVolHeader->BlockMap->Length

+                  );

+

+        HeaderLength = (UINTN) FwVolHeader->HeaderLength;

+

+        Status = FlashFdWrite (

+                  (UINTN) FwhInstance->FvBase[0],

+                  FwhInstance,

+                  (UINTN *) &HeaderLength,

+                  (UINT8 *) FwVolHeader

+                  );

+

+        FwVolHeader->HeaderLength = (UINT16) HeaderLength;

+

+        DEBUG ((EFI_D_ERROR, "Fvb (0x%x): FV header invalid, write back - %r\n", (UINTN) FwhInstance->FvBase[0], Status));

+      }

+    }

+    //

+    // The total number of blocks in the FV.

+    //

+    FwhInstance->NumOfBlocks = NumOfBlocks;

+

+    //

+    // Add a FVB Protocol Instance

+    //

+    Status = gBS->AllocatePool (

+                    EfiRuntimeServicesData,

+                    sizeof (EFI_FW_VOL_BLOCK_DEVICE),

+                    &FvbDevice

+                    );

+    ASSERT_EFI_ERROR (Status);

+

+    CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));

+

+    FvbDevice->Instance = mFvbModuleGlobal->NumFv;

+    mFvbModuleGlobal->NumFv++;

+

+    //

+    // Set up the devicepath

+    //

+    FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;

+    FvbDevice->DevicePath.MemMapDevPath.EndingAddress   = BaseAddress + (FwVolHeader->FvLength - 1);

+

+    //

+    // Find a handle with a matching device path that has supports FW Block protocol

+    //

+    TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData;

+    CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH));

+    Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);

+    if (EFI_ERROR (Status)) {

+      //

+      // LocateDevicePath fails so install a new interface and device path

+      //

+      FwbHandle = NULL;

+      Status = gBS->InstallMultipleProtocolInterfaces (

+                      &FwbHandle,

+                      &gEfiFirmwareVolumeBlockProtocolGuid,

+                      &FvbDevice->FwVolBlockInstance,

+                      &gEfiDevicePathProtocolGuid,

+                      &FvbDevice->DevicePath,

+                      NULL

+                      );

+      ASSERT_EFI_ERROR (Status);

+    } else if (IsDevicePathEnd (TempFwbDevicePath)) {

+      //

+      // Device allready exists, so reinstall the FVB protocol

+      //

+      Status = gBS->HandleProtocol (

+                      FwbHandle,

+                      &gEfiFirmwareVolumeBlockProtocolGuid,

+                      &OldFwbInterface

+                      );

+      ASSERT_EFI_ERROR (Status);

+

+      Status = gBS->ReinstallProtocolInterface (

+                      FwbHandle,

+                      &gEfiFirmwareVolumeBlockProtocolGuid,

+                      OldFwbInterface,

+                      &FvbDevice->FwVolBlockInstance

+                      );

+      ASSERT_EFI_ERROR (Status);

+

+    } else {

+      //

+      // There was a FVB protocol on an End Device Path node

+      //

+      ASSERT (FALSE);

+    }

+

+    FwhInstance = (EFI_FW_VOL_INSTANCE *)

+      (

+        (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +

+          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))

+      );

+  } while (TRUE);

+

+  //

+  // Allocate for scratch space, an intermediate buffer for FVB extention

+  //

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  MaxLbaSize,

+                  &mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL];

+

+  if (InstallSfsNotify) {

+    FvbInstallSfsNotify ();

+  }

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.c b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.c
new file mode 100644
index 0000000..11d1744
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.c
@@ -0,0 +1,210 @@
+/**@file

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

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+Module Name:

+

+    FileIo.c

+

+Abstract:

+

+  File operation for Firmware volume block driver

+

+**/

+#include "FileIo.h"

+

+//

+// Variable storage hot plug is supported but there are still some restrictions:

+// After plugging the storage back,

+// 1. Still use memory as NV if newly plugged storage is not same as the original one

+// 2. Still use memory as NV if there are some update operation during storage is unplugged.

+//

+

+

+EFI_STATUS

+FileWrite (

+  IN EFI_FILE_PROTOCOL  *File,

+  IN UINTN              Offset,

+  IN UINTN              Buffer,

+  IN UINTN              Size

+  )

+{

+  EFI_STATUS Status;

+

+  Status = File->SetPosition (File, Offset);

+  ASSERT_EFI_ERROR (Status);

+  if (!EFI_ERROR (Status)) {

+    Status = File->Write (File, &Size, (VOID *) Buffer);

+    ASSERT_EFI_ERROR (Status);

+  }

+  return Status;

+}

+

+EFI_STATUS

+CheckStore (

+  IN  EFI_HANDLE                 SimpleFileSystemHandle,

+  IN  UINT32                     VolumeId,

+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device

+  )

+{

+#define BLOCK_SIZE              0x200

+#define FAT16_VOLUME_ID_OFFSET  39

+#define FAT32_VOLUME_ID_OFFSET  67

+  EFI_STATUS                      Status;

+  EFI_BLOCK_IO_PROTOCOL           *BlkIo;

+  UINT8                           BootSector[BLOCK_SIZE];

+

+  *Device = NULL;

+  Status  = gBS->HandleProtocol (

+                   SimpleFileSystemHandle,

+                   &gEfiBlockIoProtocolGuid, // BlockIo should be supported if it supports SimpleFileSystem

+                   (VOID*)&BlkIo

+                   );

+

+  if (EFI_ERROR (Status)) {

+    goto ErrHandle;

+  }

+  if (!BlkIo->Media->MediaPresent) {

+    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media not present!\n"));

+    Status = EFI_NO_MEDIA;

+    goto ErrHandle;

+  }

+  if (BlkIo->Media->ReadOnly) {

+    DEBUG ((EFI_D_ERROR, "FwhMappedFile: Media is read-only!\n"));

+    Status = EFI_ACCESS_DENIED;

+    goto ErrHandle;

+  }

+

+  Status = BlkIo->ReadBlocks(

+                    BlkIo,

+                    BlkIo->Media->MediaId,

+                    0,

+                    BLOCK_SIZE,

+                    BootSector

+                    );

+  ASSERT_EFI_ERROR (Status);

+  if ((*(UINT32 *) &BootSector[FAT16_VOLUME_ID_OFFSET] != VolumeId) &&

+      (*(UINT32 *) &BootSector[FAT32_VOLUME_ID_OFFSET] != VolumeId)

+      ) {

+    Status = EFI_NOT_FOUND;

+    goto ErrHandle;

+  }

+

+  *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle));

+  ASSERT (*Device != NULL);

+

+ErrHandle:

+  return Status;

+}

+

+EFI_STATUS

+CheckStoreExists (

+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device

+  )

+{

+  EFI_HANDLE                        Handle;

+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;

+  EFI_STATUS                        Status;

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Device, 

+                  &Handle

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->HandleProtocol (

+                  Handle,

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Volume

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+FileClose (

+  IN  EFI_FILE_PROTOCOL          *File

+  )

+{

+  File->Flush (File);

+  File->Close (File);

+}

+EFI_STATUS

+FileOpen (

+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device,

+  IN  CHAR16                     *MappedFile,

+  OUT EFI_FILE_PROTOCOL          **File,

+  IN  UINT64                     OpenMode

+  )

+{  

+  EFI_HANDLE                        Handle;

+  EFI_FILE_HANDLE                   Root;

+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Volume;

+  EFI_STATUS                        Status;

+

+  *File = NULL;

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Device, 

+                  &Handle

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->HandleProtocol (

+                  Handle,

+                  &gEfiSimpleFileSystemProtocolGuid,

+                  &Volume

+                  );

+  ASSERT_EFI_ERROR (Status);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  //

+  // Open the root directory of the volume

+  //

+  Root = NULL;

+  Status = Volume->OpenVolume (

+                     Volume,

+                     &Root

+                     );

+  ASSERT_EFI_ERROR (Status);

+  ASSERT (Root != NULL);

+

+  //

+  // Open file

+  //

+  Status = Root->Open (

+                   Root,

+                   File,

+                   MappedFile,

+                   OpenMode,

+                   0

+                   );

+  if (EFI_ERROR (Status)) {

+    *File = NULL;

+  }

+

+  //

+  // Close the Root directory

+  //

+  Root->Close (Root);

+  return Status;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.h b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.h
new file mode 100644
index 0000000..7323697
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FileIo.h
@@ -0,0 +1,58 @@
+/**@file

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FileIo.h

+  

+Abstract:

+

+  File operation for Firmware volume block driver

+

+**/

+#ifndef _FW_BLOCK_SERVICE_FILE_IO_H

+#define _FW_BLOCK_SERVICE_FILE_IO_H

+

+#include "FwBlockService.h"

+

+EFI_STATUS

+FileWrite (

+  IN EFI_FILE_PROTOCOL  *File,

+  IN UINTN              Offset,

+  IN UINTN              Buffer,

+  IN UINTN              Size

+  );

+

+EFI_STATUS

+CheckStore (

+  IN  EFI_HANDLE                 SimpleFileSystemHandle,

+  IN  UINT32                     VolumeId,

+  OUT EFI_DEVICE_PATH_PROTOCOL   **Device

+  );

+

+EFI_STATUS

+CheckStoreExists (

+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device

+  );

+

+EFI_STATUS

+FileOpen (

+  IN  EFI_DEVICE_PATH_PROTOCOL   *Device,

+  IN  CHAR16                     *MappedFile,

+  OUT EFI_FILE_PROTOCOL          **File,

+  IN  UINT64                     OpenMode

+  );

+

+VOID

+FileClose (

+  IN  EFI_FILE_PROTOCOL          *File

+  );

+

+#endif // _FW_BLOCK_SERVICE_FILE_IO_H

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FvbInfo.c b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FvbInfo.c
new file mode 100644
index 0000000..fa73783
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FvbInfo.c
@@ -0,0 +1,121 @@
+/**@file

+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FvbInfo.c

+

+Abstract:

+

+  Defines data structure that is the volume header found.These data is intent

+  to decouple FVB driver with FV header.

+

+**/

+#include "FileIo.h"

+#include "FlashLayout.h"

+

+typedef struct {

+  UINT64                      FvLength;

+  EFI_FIRMWARE_VOLUME_HEADER  FvbInfo;

+  EFI_FV_BLOCK_MAP_ENTRY      End;

+} EFI_FVB_MEDIA_INFO;

+

+#define FVB_MEDIA_BLOCK_SIZE    FIRMWARE_BLOCK_SIZE

+#define RECOVERY_BOIS_BLOCK_NUM FIRMWARE_BLOCK_NUMBER

+#define SYSTEM_NV_BLOCK_NUM     2

+

+EFI_FVB_MEDIA_INFO  mPlatformFvbMediaInfo[] = {

+  //

+  // Systen NvStorage FVB

+  //

+  {

+    NV_STORAGE_FVB_SIZE,

+    {

+      {

+        0,

+      },  // ZeroVector[16]

+      EFI_SYSTEM_NV_DATA_FV_GUID,

+      NV_STORAGE_FVB_SIZE,

+      EFI_FVH_SIGNATURE,

+      EFI_FVB2_READ_ENABLED_CAP |

+        EFI_FVB2_READ_STATUS |

+        EFI_FVB2_WRITE_ENABLED_CAP |

+        EFI_FVB2_WRITE_STATUS |

+        EFI_FVB2_ERASE_POLARITY,

+      sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),

+      0,  // CheckSum

+      0,  // ExtHeaderOffset

+      {

+        0,

+      },  // Reserved[1]

+      1,  // Revision

+      {

+        NV_STORAGE_FVB_BLOCK_NUM,

+        FV_BLOCK_SIZE,

+      }

+    },

+    {

+      0,

+      0

+    }

+  },

+  //

+  // System FTW FVB

+  //

+  {

+    NV_FTW_FVB_SIZE,

+    {

+      {

+        0,

+      },  // ZeroVector[16]

+      EFI_SYSTEM_NV_DATA_FV_GUID,

+      NV_FTW_FVB_SIZE,

+      EFI_FVH_SIGNATURE,

+      EFI_FVB2_READ_ENABLED_CAP |

+        EFI_FVB2_READ_STATUS |

+        EFI_FVB2_WRITE_ENABLED_CAP |

+        EFI_FVB2_WRITE_STATUS |

+        EFI_FVB2_ERASE_POLARITY,

+      sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),

+      0,  // CheckSum

+      0,  // ExtHeaderOffset

+      {

+        0,

+      },  // Reserved[1]

+      1,  // Revision

+      {

+        NV_FTW_FVB_BLOCK_NUM,

+        FV_BLOCK_SIZE,

+      }

+    },

+    {

+      0,

+      0

+    }

+  }

+};

+

+EFI_STATUS

+GetFvbInfo (

+  IN  UINT64                        FvLength,

+  OUT EFI_FIRMWARE_VOLUME_HEADER    **FvbInfo

+  )

+{

+  UINTN Index;

+

+  for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); Index += 1) {

+    if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) {

+      *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo;

+      return EFI_SUCCESS;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FwBlockService.h b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FwBlockService.h
new file mode 100644
index 0000000..b14f10a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/FvbRuntimeService/FwBlockService.h
@@ -0,0 +1,298 @@
+/**@file

+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FwBlockService.h

+  

+Abstract:

+

+  Firmware volume block driver for Intel Firmware Hub (FWH) device

+

+**/

+#ifndef _FW_BLOCK_SERVICE_H

+#define _FW_BLOCK_SERVICE_H

+

+//

+// The package level header files this module uses

+//

+#include <PiDxe.h>

+

+//

+// The protocols, PPI and GUID defintions for this module

+//

+#include <Guid/EventGroup.h>

+#include <Guid/FirmwareFileSystem2.h>

+#include <Protocol/FirmwareVolumeBlock.h>

+#include <Protocol/DevicePath.h>

+#include <Protocol/SimpleFileSystem.h>

+#include <Protocol/BlockIo.h>

+#include <Library/DevicePathLib.h>

+#include <Guid/SystemNvDataGuid.h>

+#include <Guid/FlashMapHob.h>

+#include <Guid/HobList.h>

+

+//

+// The Library classes this module consumes

+//

+#include <Library/UefiLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/BaseLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/UefiRuntimeLib.h>

+#include <Library/DebugLib.h>

+#include <Library/HobLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/PcdLib.h>

+

+

+#define FWH_READ_LOCK                   (1 << 2)

+#define FWH_LOCK_DOWN                   (1 << 1)

+#define FWH_WRITE_LOCK                  1

+#define FWH_WRITE_STATE_STATUS          (1 << 7)

+#define FWH_ERASE_STATUS                (1 << 5)

+#define FWH_PROGRAM_STATUS              (1 << 4)

+#define FWH_VPP_STATUS                  (1 << 3)

+#define STALL_TIME                      5

+#define FWH_ERASE_STATUS_BITS           (FWH_ERASE_STATUS || FWH_VPP_STATUS)

+#define FWH_WRITE_STATUS_BITS           (FWH_WRITE_STATUS || FWH_VPP_STATUS)

+

+//

+// BugBug: Add documentation here for data structure!!!!

+//

+#define FVB_PHYSICAL  0

+#define FVB_VIRTUAL   1

+

+#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \

+                              EFI_FVB2_READ_ENABLED_CAP | \

+                              EFI_FVB2_WRITE_DISABLED_CAP | \

+                              EFI_FVB2_WRITE_ENABLED_CAP | \

+                              EFI_FVB2_LOCK_CAP \

+                              )

+#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)

+

+typedef struct {

+  EFI_LOCK                    FvbDevLock;

+  UINTN                       FvBase[2];

+  //

+  // We can treat VolumeSignature combined with MappedFile 

+  //  as a unique key to locate the mapped file.

+#define MAX_PATH 256

+  UINT32                      VolumeId;

+  CHAR16                      MappedFile[MAX_PATH];

+  UINT32                      ActuralSize;

+  UINT32                      Offset;

+  

+  EFI_DEVICE_PATH_PROTOCOL    *Device; // only used in BS period, won't use after memory map changed

+  UINTN                       NumOfBlocks;

+  BOOLEAN                     WriteEnabled;

+  EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;

+} EFI_FW_VOL_INSTANCE;

+

+typedef struct {

+  UINT32              NumFv;

+  EFI_FW_VOL_INSTANCE *FvInstance[2];

+  UINT8               *FvbScratchSpace[2];

+} ESAL_FWB_GLOBAL;

+

+//

+// Fvb Protocol instance data

+//

+#define FVB_DEVICE_FROM_THIS(a)         CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)

+#define FVB_EXTEND_DEVICE_FROM_THIS(a)  CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE)

+#define FVB_DEVICE_SIGNATURE            SIGNATURE_32 ('F', 'V', 'B', 'C')

+

+typedef struct {

+  MEMMAP_DEVICE_PATH        MemMapDevPath;

+  EFI_DEVICE_PATH_PROTOCOL  EndDevPath;

+} FV_DEVICE_PATH;

+

+typedef struct {

+  UINTN                               Signature;

+  FV_DEVICE_PATH                      DevicePath;

+  UINTN                               Instance;

+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  FwVolBlockInstance;

+} EFI_FW_VOL_BLOCK_DEVICE;

+

+EFI_STATUS

+GetFvbInfo (

+  IN  EFI_PHYSICAL_ADDRESS              FvBaseAddress,

+  OUT EFI_FIRMWARE_VOLUME_HEADER        **FvbInfo

+  );

+

+EFI_STATUS

+EnableFvbWrites (

+  IN  BOOLEAN   EnableWrites

+  );

+

+EFI_STATUS

+PlatformGetFvbWriteBase (

+  IN  UINTN     CurrentBaseAddress,

+  IN  UINTN     *NewBaseAddress,

+  IN  BOOLEAN   *WriteEnabled

+  );

+

+EFI_STATUS

+EnablePlatformFvb (

+  VOID

+  );

+

+BOOLEAN

+SetPlatformFvbLock (

+  IN UINTN  LbaAddress

+  );

+

+EFI_STATUS

+FvbReadBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN UINTN                                BlockOffset,

+  IN OUT UINTN                            *NumBytes,

+  IN UINT8                                *Buffer,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+FvbWriteBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN UINTN                                BlockOffset,

+  IN OUT UINTN                            *NumBytes,

+  IN UINT8                                *Buffer,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+FvbEraseBlock (

+  IN UINTN                                Instance,

+  IN EFI_LBA                              Lba,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+FvbSetVolumeAttributes (

+  IN UINTN                                Instance,

+  IN OUT EFI_FVB_ATTRIBUTES_2             *Attributes,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+FvbGetVolumeAttributes (

+  IN UINTN                                Instance,

+  OUT EFI_FVB_ATTRIBUTES_2                *Attributes,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+FvbGetPhysicalAddress (

+  IN UINTN                                Instance,

+  OUT EFI_PHYSICAL_ADDRESS                *Address,

+  IN ESAL_FWB_GLOBAL                      *Global,

+  IN BOOLEAN                              Virtual

+  );

+

+EFI_STATUS

+EFIAPI

+FvbInitialize (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  );

+

+VOID

+EFIAPI

+FvbClassAddressChangeEvent (

+  IN EFI_EVENT        Event,

+  IN VOID             *Context

+  );

+

+EFI_STATUS

+FvbSpecificInitialize (

+  IN  ESAL_FWB_GLOBAL   *mFvbModuleGlobal

+  );

+

+EFI_STATUS

+FvbGetLbaAddress (

+  IN  UINTN                               Instance,

+  IN  EFI_LBA                             Lba,

+  OUT UINTN                               *LbaAddress,

+  OUT UINTN                               *LbaLength,

+  OUT UINTN                               *NumOfBlocks,

+  IN  ESAL_FWB_GLOBAL                     *Global,

+  IN  BOOLEAN                             Virtual

+  );

+

+//

+// Protocol APIs

+//

+EFI_STATUS

+EFIAPI

+FvbProtocolGetAttributes (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,

+  OUT      EFI_FVB_ATTRIBUTES_2                        *Attributes

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolSetAttributes (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL       *This,

+  IN OUT   EFI_FVB_ATTRIBUTES_2                     *Attributes

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetPhysicalAddress (

+  IN  CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL          *This,

+  OUT       EFI_PHYSICAL_ADDRESS                        *Address

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolGetBlockSize (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL           *This,

+  IN  EFI_LBA                                     Lba,

+  OUT UINTN                                       *BlockSize,

+  OUT UINTN                                       *NumOfBlocks

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolRead (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,

+  IN EFI_LBA                                      Lba,

+  IN UINTN                                        Offset,

+  IN OUT UINTN                                    *NumBytes,

+  IN UINT8                                        *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolWrite (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,

+  IN EFI_LBA                                      Lba,

+  IN UINTN                                        Offset,

+  IN OUT UINTN                                    *NumBytes,

+  IN UINT8                                        *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+FvbProtocolEraseBlocks (

+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,

+  ...  

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/GetVariables.bat b/uefi/linaro-edk2/DuetPkg/GetVariables.bat
new file mode 100644
index 0000000..c781228
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/GetVariables.bat
@@ -0,0 +1,38 @@
+@REM ## @file

+@REM #

+@REM #  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+@REM #

+@REM #  This program and the accompanying materials

+@REM #  are licensed and made available under the terms and conditions of the BSD License

+@REM #  which accompanies this distribution. The full text of the license may be found at

+@REM #  http://opensource.org/licenses/bsd-license.php

+@REM #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+@REM #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+@REM #

+@REM #

+@REM ##

+

+

+@REM Read the variables from Conf/target.txt

+@REM Because we can't add '=' as a delimiter in 'for', each variable is read in 2 parts:

+@REM First we read the "= xyz" part of the variable assignation which we use, along with

+@REM the original equal sign for our first assignation. Then we trim any left whitespaces.

+@REM NB: default token delimiters for "for /f" are tab and space.

+

+@set CONFIG_FILE=%WORKSPACE%\Conf\target.txt

+

+@for /f "tokens=1*" %%i in ('type %CONFIG_FILE% ^| find "TOOL_CHAIN_TAG" ^| find /V "#"') do @set TOOL_CHAIN_TAG%%j

+@for /f "tokens=*" %%i in ("%TOOL_CHAIN_TAG%") do @set TOOL_CHAIN_TAG=%%i

+

+@for /f "tokens=1*" %%i in ('type %CONFIG_FILE% ^| find "TARGET" ^| find /V "#" ^| find /V "TARGET_ARCH"') do @set TARGET%%j

+@for /f "tokens=*" %%i in ("%TARGET%") do @set TARGET=%%i

+

+@for /f "tokens=1*" %%i in ('type %CONFIG_FILE% ^| find "TARGET_ARCH" ^|find /V "#"') do @set TARGET_ARCH%%j

+@for /f "tokens=*" %%i in ("%TARGET_ARCH%") do @set TARGET_ARCH=%%i

+

+

+@REM Set defaults if above variables are undefined in target.txt

+

+@if "%TOOL_CHAIN_TAG%%"=="" @set TOOL_CHAIN_TAG=MYTOOLS

+@if "%TARGET%"=="" @set TARGET=DEBUG

+@if "%TARGET_ARCH%"=="" @set TARGET_ARCH=IA32

diff --git a/uefi/linaro-edk2/DuetPkg/Include/EfiFlashMap.h b/uefi/linaro-edk2/DuetPkg/Include/EfiFlashMap.h
new file mode 100644
index 0000000..f36ee3b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/EfiFlashMap.h
@@ -0,0 +1,153 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  EfiFlashMap.h

+

+Abstract:

+

+  Defines for the EFI Flash Map functionality

+  

+**/

+

+#ifndef _EFI_FLASHMAP_H_

+#define _EFI_FLASHMAP_H_

+

+//

+// Definition for flash map GUIDed HOBs

+//

+typedef UINT32  EFI_FLASH_AREA_ATTRIBUTES;

+

+#define EFI_FLASH_AREA_FV           0x0001

+#define EFI_FLASH_AREA_SUBFV        0x0002

+#define EFI_FLASH_AREA_MEMMAPPED_FV 0x0004

+#define EFI_FLASH_AREA_REQUIRED     0x0008

+#define EFI_FLASH_AREA_CORRUPT      0x0010

+

+typedef UINT8   EFI_FLASH_AREA_TYPE;

+

+#define EFI_FLASH_AREA_RECOVERY_BIOS  0x0   // Recovery code

+#define EFI_FLASH_AREA_MAIN_BIOS      0x1   // Regular BIOS code

+#define EFI_FLASH_AREA_PAL_B          0x2   // PAL-B

+#define EFI_FLASH_AREA_RESERVED_03    0x3   // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_RESERVED_04    0x4   // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_DMI_FRU        0x5   // DMI FRU information

+#define EFI_FLASH_AREA_OEM_BINARY     0x6   // OEM Binary Code/data

+#define EFI_FLASH_AREA_RESERVED_07    0x7   // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_RESERVED_08    0x8   // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_RESERVED_09    0x9   // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_RESERVED_0A    0x0a  // Reserved for backwards compatibility

+#define EFI_FLASH_AREA_EFI_VARIABLES  0x0b  // EFI variables

+#define EFI_FLASH_AREA_MCA_LOG        0x0c  // MCA error log

+#define EFI_FLASH_AREA_SMBIOS_LOG     0x0d  // SMBIOS error log

+#define EFI_FLASH_AREA_FTW_BACKUP     0x0e  // A backup block during FTW operations

+#define EFI_FLASH_AREA_FTW_STATE      0x0f  // State information during FTW operations

+#define EFI_FLASH_AREA_UNUSED         0x0fd // Not used

+#define EFI_FLASH_AREA_GUID_DEFINED   0x0fe // Usage defined by a GUID

+#pragma pack(1)

+//

+// An individual sub-area Entry.

+// A single flash area may consist of  more than one sub-area.

+//

+/**

+typedef struct {

+  EFI_FLASH_AREA_ATTRIBUTES Attributes;

+  UINT32                    Reserved;

+  EFI_PHYSICAL_ADDRESS      Base;

+  EFI_PHYSICAL_ADDRESS      Length;

+  EFI_GUID                  FileSystem;

+} EFI_FLASH_SUBAREA_ENTRY;

+

+typedef struct {

+  UINT8                   Reserved[3];

+  EFI_FLASH_AREA_TYPE     AreaType;

+  EFI_GUID                AreaTypeGuid;

+  UINT32                  NumEntries;

+  EFI_FLASH_SUBAREA_ENTRY Entries[1];

+} EFI_FLASH_MAP_ENTRY_DATA;

+

+typedef struct {

+  UINT8                   Reserved[3];

+  EFI_FLASH_AREA_TYPE     AreaType;

+  EFI_GUID                AreaTypeGuid;

+  UINT32                  NumberOfEntries;

+  EFI_FLASH_SUBAREA_ENTRY Entries[1];

+  //

+  // Extended Hob data.

+  //

+  // VolumeId and FilePath indicating a unique file.

+  //

+  UINT32                  VolumeId;

+  CHAR16                  FilePath[256];

+  UINT32                  ActuralSize;

+  UINT32                  Offset;

+} EFI_FLASH_MAP_FS_ENTRY_DATA;

+

+typedef struct {

+  EFI_HOB_GENERIC_HEADER  Header;

+  EFI_GUID                Name;

+  UINT8                   Reserved[3];

+  EFI_FLASH_AREA_TYPE     AreaType;

+  EFI_GUID                AreaTypeGuid;

+  UINT32                  NumEntries;

+  EFI_FLASH_SUBAREA_ENTRY Entries[1];

+} EFI_HOB_FLASH_MAP_ENTRY_TYPE;

+

+//

+// Internal definitions

+//

+typedef struct {

+  UINT8                   Reserved[3];

+  EFI_FLASH_AREA_TYPE     AreaType;

+  EFI_GUID                AreaTypeGuid;

+  UINT32                  NumberOfEntries;

+  EFI_FLASH_SUBAREA_ENTRY SubAreaData;

+} EFI_FLASH_AREA_HOB_DATA;

+

+typedef struct {

+  UINTN                     Base;

+  UINTN                     Length;

+  EFI_FLASH_AREA_ATTRIBUTES Attributes;

+  EFI_FLASH_AREA_TYPE       AreaType;

+  UINT8                     Reserved[3];

+  EFI_GUID                  AreaTypeGuid;

+} EFI_FLASH_AREA_DATA;

+**/

+

+typedef struct {

+  EFI_FLASH_AREA_ATTRIBUTES Attributes;

+  UINT32                    Reserved;

+  EFI_PHYSICAL_ADDRESS      Base;

+  EFI_PHYSICAL_ADDRESS      Length;

+  EFI_GUID                  FileSystem;

+} EFI_FLASH_SUBAREA_ENTRY;

+

+typedef struct {

+  UINT8                   Reserved[3];

+  EFI_FLASH_AREA_TYPE     AreaType;

+  EFI_GUID                AreaTypeGuid;

+  UINT32                  NumberOfEntries;

+  EFI_FLASH_SUBAREA_ENTRY Entries[1];

+  //

+  // Extended Hob data.

+  //

+  // VolumeId and FilePath indicating a unique file.

+  //

+  UINT32                  VolumeId;

+  CHAR16                  FilePath[258];

+  UINT32                  ActuralSize;

+  UINT32                  Offset;

+} EFI_FLASH_MAP_FS_ENTRY_DATA;

+

+#pragma pack()

+

+#endif // #ifndef _EFI_FLASHMAP_H_

diff --git a/uefi/linaro-edk2/DuetPkg/Include/EfiLdrHandoff.h b/uefi/linaro-edk2/DuetPkg/Include/EfiLdrHandoff.h
new file mode 100644
index 0000000..9bbe94e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/EfiLdrHandoff.h
@@ -0,0 +1,59 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  EfiLdrHandoff.h

+

+Abstract:

+

+Revision History:

+

+**/

+

+#ifndef _EFILDR_HANDOFF_H_

+#define _EFILDR_HANDOFF_H_

+

+#include <Base.h>

+#include <Uefi.h>

+

+#define EFILDR_BASE_SEGMENT 0x2000

+#define EFILDR_LOAD_ADDRESS        (EFILDR_BASE_SEGMENT << 4)

+#define EFILDR_HEADER_ADDRESS      (EFILDR_LOAD_ADDRESS+0x2000)

+

+#define EFILDR_CB_VA        0x00

+

+typedef struct _EFILDRHANDOFF {

+    UINTN                    MemDescCount;

+    EFI_MEMORY_DESCRIPTOR   *MemDesc;

+    VOID                    *BfvBase;

+    UINTN                   BfvSize;

+    VOID                    *DxeIplImageBase;

+    UINTN                   DxeIplImageSize;

+    VOID                    *DxeCoreImageBase;

+    UINTN                   DxeCoreImageSize;

+    VOID                    *DxeCoreEntryPoint;

+} EFILDRHANDOFF;

+

+typedef struct {

+    UINT32       CheckSum;

+    UINT32       Offset;

+    UINT32       Length;

+    UINT8        FileName[52];

+} EFILDR_IMAGE;

+

+typedef struct {          

+    UINT32       Signature;     

+    UINT32       HeaderCheckSum;

+    UINT32       FileLength;

+    UINT32       NumberOfImages;

+} EFILDR_HEADER;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/FlashLayout.h b/uefi/linaro-edk2/DuetPkg/Include/FlashLayout.h
new file mode 100644
index 0000000..777adea
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/FlashLayout.h
@@ -0,0 +1,44 @@
+/** @file

+

+Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FlashLayout.h

+   

+Abstract:

+

+  Platform specific flash layout

+

+**/

+

+#ifndef _EFI_FLASH_LAYOUT

+#define _EFI_FLASH_LAYOUT

+

+#include "EfiFlashMap.h"

+

+//

+// Firmware Volume Information for DUET

+//

+#define FV_BLOCK_SIZE               0x10000

+#define FV_BLOCK_MASK               0x0FFFF

+#define EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH  (sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY))

+

+#define NV_STORAGE_SIZE             0x4000

+#define NV_STORAGE_FVB_SIZE         ((NV_STORAGE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + FV_BLOCK_MASK) & ~FV_BLOCK_MASK)

+#define NV_STORAGE_FVB_BLOCK_NUM    (NV_STORAGE_FVB_SIZE / FV_BLOCK_SIZE)

+

+#define NV_FTW_WORKING_SIZE         0x2000

+#define NV_FTW_SPARE_SIZE           0x10000

+#define NV_FTW_FVB_SIZE             ((NV_FTW_WORKING_SIZE + NV_FTW_SPARE_SIZE + EFI_RUNTIME_UPDATABLE_FV_HEADER_LENGTH + FV_BLOCK_MASK) & ~FV_BLOCK_MASK)

+#define NV_FTW_FVB_BLOCK_NUM        (NV_FTW_FVB_SIZE / FV_BLOCK_SIZE)

+

+#define NV_STORAGE_FILE_PATH        L".\\Efivar.bin"

+#endif // _EFI_FLASH_LAYOUT

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/AcpiDescription.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/AcpiDescription.h
new file mode 100644
index 0000000..96c7488
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/AcpiDescription.h
@@ -0,0 +1,109 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+    AcpiDescription.h

+    

+Abstract:

+

+

+   GUIDs used for ACPI Description

+

+**/

+

+#ifndef _EFI_ACPI_DESCRIPTION_H_

+#define _EFI_ACPI_DESCRIPTION_H_

+

+#include <IndustryStandard/Acpi.h>

+

+#define EFI_ACPI_DESCRIPTION_GUID \

+  { \

+  0x3c699197, 0x93c, 0x4c69, {0xb0, 0x6b, 0x12, 0x8a, 0xe3, 0x48, 0x1d, 0xc9} \

+  }

+

+//

+// Following structure defines ACPI Description information.

+// This information is platform specific, may be consumed by DXE generic driver.

+//

+#pragma pack(1)

+typedef struct _EFI_ACPI_DESCRIPTION {

+  //

+  // For Timer

+  //

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM_TMR_BLK;

+  UINT8                                    PM_TMR_LEN;

+  UINT8                                    TMR_VAL_EXT;

+

+  //

+  // For RTC

+  //

+  UINT8                                    DAY_ALRM;

+  UINT8                                    MON_ALRM;

+  UINT8                                    CENTURY;

+

+  //

+  // For Reset

+  //

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   RESET_REG;

+  UINT8                                    RESET_VALUE;

+

+  //

+  // For Shutdown

+  //

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM1a_EVT_BLK;

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM1b_EVT_BLK;

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM1a_CNT_BLK;

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM1b_CNT_BLK;

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   PM2_CNT_BLK;

+  UINT8                                    PM1_EVT_LEN;

+  UINT8                                    PM1_CNT_LEN;

+  UINT8                                    PM2_CNT_LEN;

+  UINT8                                    SLP_TYPa;

+  UINT8                                    SLP_TYPb;

+

+  //

+  // For sleep

+  //

+  UINT8                                    SLP1_TYPa;

+  UINT8                                    SLP1_TYPb;

+  UINT8                                    SLP2_TYPa;

+  UINT8                                    SLP2_TYPb;

+  UINT8                                    SLP3_TYPa;

+  UINT8                                    SLP3_TYPb;

+  UINT8                                    SLP4_TYPa;

+  UINT8                                    SLP4_TYPb;

+

+  //

+  // GPE

+  //

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   GPE0_BLK;

+  EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE   GPE1_BLK;

+  UINT8                                    GPE0_BLK_LEN;

+  UINT8                                    GPE1_BLK_LEN;

+  UINT8                                    GPE1_BASE;

+

+  //

+  // IAPC Boot Arch

+  //

+  UINT16                                   IAPC_BOOT_ARCH;

+

+  //

+  // Flags

+  //

+  UINT32                                   Flags;

+

+} EFI_ACPI_DESCRIPTION;

+#pragma pack()

+

+extern EFI_GUID gEfiAcpiDescriptionGuid;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/ConsoleOutConfig.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/ConsoleOutConfig.h
new file mode 100644
index 0000000..48861a5
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/ConsoleOutConfig.h
@@ -0,0 +1,33 @@
+/**@file

+  Setup Variable data structure for Duet platform.

+

+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.   

+

+**/

+

+#ifndef __DUET_CONSOLEOUT_CONFIG_H__

+#define __DUET_CONSOLEOUT_CONFIG_H__

+

+#define DUET_CONSOLEOUT_CONFIG_GUID  \

+  { 0xED150714, 0xDF30, 0x407D, { 0xB2, 0x4A, 0x4B, 0x74, 0x2F, 0xD5, 0xCE, 0xA2 } }

+

+#pragma pack(1)

+typedef struct {

+  //

+  // Console output mode

+  //

+  UINT32        ConOutColumn;

+  UINT32        ConOutRow;

+} DUET_CONSOLEOUT_CONFIG;

+#pragma pack()

+

+extern EFI_GUID   gDuetConsoleOutConfigGuid;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/DxeCoreFileName.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/DxeCoreFileName.h
new file mode 100644
index 0000000..24c0a15
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/DxeCoreFileName.h
@@ -0,0 +1,23 @@
+/** @file

+  Guid is EDKII DxeCore moudle GUID.

+

+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#ifndef __DXE_CORE_FILE_NAME__

+#define __DXE_CORE_FILE_NAME__

+

+#define DXE_CORE_FILE_NAME_GUID \

+  { 0xD6A2CB7F, 0x6A18, 0x4e2f, {0xB4, 0x3B, 0x99, 0x20, 0xA7, 0x33, 0x70, 0x0A }}

+

+extern EFI_GUID gDxeCoreFileNameGuid;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/FlashMapHob.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/FlashMapHob.h
new file mode 100644
index 0000000..8ae0ad8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/FlashMapHob.h
@@ -0,0 +1,33 @@
+/** @file

+

+Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  FlashMapHob.h

+    

+Abstract:

+

+  GUID used for Flash Map HOB entries in the HOB list.

+

+**/

+

+#ifndef _FLASH_MAP_HOB_GUID_H_

+#define _FLASH_MAP_HOB_GUID_H_

+

+//

+// Definitions for Flash Map

+//

+#define EFI_FLASH_MAP_HOB_GUID \

+  { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59} }

+

+extern EFI_GUID gEfiFlashMapHobGuid;

+

+#endif // _FLASH_MAP_HOB_GUID_H_

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/LdrMemoryDescriptor.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/LdrMemoryDescriptor.h
new file mode 100644
index 0000000..5fd7aa1
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/LdrMemoryDescriptor.h
@@ -0,0 +1,33 @@
+/** @file

+  Guid is for GUIDED HOB of LDR memory descriptor.

+

+Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#ifndef __LDR_MEMORY_DESCRIPTOR__

+#define __LDR_MEMORY_DESCRIPTOR__

+

+#define LDR_MEMORY_DESCRIPTOR_GUID \

+  { 0x7701d7e5, 0x7d1d, 0x4432, {0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60}}

+

+#pragma pack(1)

+

+typedef struct {

+  EFI_HOB_GUID_TYPE             Hob;

+  UINTN                         MemDescCount;

+  EFI_MEMORY_DESCRIPTOR         *MemDesc;

+} MEMORY_DESC_HOB;

+

+#pragma pack()

+

+extern EFI_GUID gLdrMemoryDescriptorGuid;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/PciExpressBaseAddress.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/PciExpressBaseAddress.h
new file mode 100644
index 0000000..6ee5a58
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/PciExpressBaseAddress.h
@@ -0,0 +1,46 @@
+/** @file

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+    PciExpressBaseAddress.h

+    

+Abstract:

+

+

+   GUIDs used for PciExpress Base Address

+

+**/

+

+#ifndef _EFI_PCI_EXPRESS_BASE_ADDRESS_H_

+#define _EFI_PCI_EXPRESS_BASE_ADDRESS_H_

+

+#define EFI_PCI_EXPRESS_BASE_ADDRESS_GUID \

+  { \

+  0x3677d529, 0x326f, 0x4603, {0xa9, 0x26, 0xea, 0xac, 0xe0, 0x1d, 0xcb, 0xb0} \

+  }

+

+//

+// Following structure defines PCI Express Base Address information.

+// This information is platform specific, and built into hob in PEI phase.

+// It can be consumed by PEI PCI driver and DXE PCI driver.

+//

+#pragma pack(1)

+typedef struct _EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION {

+  UINT32       HostBridgeNumber;

+  UINT32       RootBridgeNumber;

+  UINT64       PciExpressBaseAddress;

+} EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION;

+#pragma pack()

+

+extern EFI_GUID gEfiPciExpressBaseAddressGuid;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/Include/Guid/PciOptionRomTable.h b/uefi/linaro-edk2/DuetPkg/Include/Guid/PciOptionRomTable.h
new file mode 100644
index 0000000..2325d9b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Include/Guid/PciOptionRomTable.h
@@ -0,0 +1,41 @@
+/** @file

+  GUID and data structure used to describe the list of PCI Option ROMs present in a system.

+  

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+**/

+

+#ifndef __PCI_OPTION_ROM_TABLE_GUID_H_

+#define __PCI_OPTION_ROM_TABLE_GUID_H_

+

+#define EFI_PCI_OPTION_ROM_TABLE_GUID \

+  { 0x7462660f, 0x1cbd, 0x48da, {0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c } }

+

+extern EFI_GUID gEfiPciOptionRomTableGuid;

+

+typedef struct {

+  EFI_PHYSICAL_ADDRESS   RomAddress; 

+  EFI_MEMORY_TYPE        MemoryType;

+  UINT32                 RomLength; 

+  UINT32                 Seg; 

+  UINT8                  Bus; 

+  UINT8                  Dev; 

+  UINT8                  Func; 

+  BOOLEAN                ExecutedLegacyBiosImage; 

+  BOOLEAN                DontLoadEfiRom;

+} EFI_PCI_OPTION_ROM_DESCRIPTOR;

+

+typedef struct {

+  UINT64                         PciOptionRomCount;

+  EFI_PCI_OPTION_ROM_DESCRIPTOR   *PciOptionRomDescriptors;

+} EFI_PCI_OPTION_ROM_TABLE;

+

+#endif // __PCI_OPTION_ROM_TABLE_GUID_H_

+

diff --git a/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.c b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.c
new file mode 100644
index 0000000..1fd3ecf
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.c
@@ -0,0 +1,125 @@
+/*++

+

+Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  LegacyMetronome.c

+

+Abstract:

+

+  This contains the installation function for the driver.

+

+--*/

+

+#include "Metronome.h"

+

+//

+// Handle for the Metronome Architectural Protocol instance produced by this driver

+//

+EFI_HANDLE                  mMetronomeHandle = NULL;

+

+//

+// The Metronome Architectural Protocol instance produced by this driver

+//

+EFI_METRONOME_ARCH_PROTOCOL mMetronome = {

+  WaitForTick,

+  TICK_PERIOD

+};

+

+//

+// Worker Functions

+//

+EFI_STATUS

+EFIAPI

+WaitForTick (

+  IN EFI_METRONOME_ARCH_PROTOCOL  *This,

+  IN UINT32                       TickNumber

+  )

+/*++

+

+Routine Description:

+

+  Waits for the TickNumber of ticks from a known platform time source.

+

+Arguments:

+

+  This                Pointer to the protocol instance.

+

+Returns: 

+

+  EFI_SUCCESS         If number of ticks occurred.

+  EFI_NOT_FOUND       Could not locate CPU IO protocol

+

+--*/

+// TODO:    TickNumber - add argument and description to function comment

+{

+  //

+  // Wait for TickNumber toggles of the Refresh bit

+  //

+  for (; TickNumber != 0x00; TickNumber--) {

+    while ((IoRead8(REFRESH_PORT) & REFRESH_ON) == REFRESH_ON);

+    while ((IoRead8(REFRESH_PORT) & REFRESH_ON) == REFRESH_OFF);

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+InstallMetronome (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+/*++

+

+Routine Description:

+  

+  Install the LegacyMetronome driver.  Loads a Metronome Arch Protocol based

+  on the Port 61 timer.

+

+Arguments:

+

+  (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)

+

+Returns:

+

+  EFI_SUCCESS - Metronome Architectural Protocol Installed

+

+--*/

+// TODO:    ImageHandle - add argument and description to function comment

+// TODO:    SystemTable - add argument and description to function comment

+{

+  EFI_STATUS  Status;

+

+  //

+  // Make sure the Metronome Architectural Protocol is not already installed in the system

+  //

+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMetronomeArchProtocolGuid);

+

+  //

+  // Program port 61 timer 1 as refresh timer. We could use ACPI timer in the

+  // future.

+  //

+  IoWrite8 (TIMER1_CONTROL_PORT, LOAD_COUNTER1_LSB);

+  IoWrite8 (TIMER1_COUNT_PORT, COUNTER1_COUNT);

+

+  //

+  // Install on a new handle

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &mMetronomeHandle,

+                  &gEfiMetronomeArchProtocolGuid,

+                  &mMetronome,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.h b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.h
new file mode 100644
index 0000000..a543507
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.h
@@ -0,0 +1,75 @@
+/*++

+

+Copyright (c) 2005, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  LegacyMetronome.h

+

+Abstract:

+

+  Driver implementing the EFI 2.0 metronome protocol using the legacy PORT 61 

+  timer.

+

+--*/

+

+#ifndef _LEGACY_METRONOME_H

+#define _LEGACY_METRONOME_H

+

+//

+// Statements that include other files

+//

+#include <PiDxe.h>

+

+#include <Protocol/Metronome.h>

+

+#include <Library/DebugLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/IoLib.h>

+

+//

+// Private definitions

+//

+#define TICK_PERIOD         300

+#define REFRESH_PORT        0x61

+#define REFRESH_ON          0x10

+#define REFRESH_OFF         0x00

+#define TIMER1_CONTROL_PORT 0x43

+#define TIMER1_COUNT_PORT   0x41

+#define LOAD_COUNTER1_LSB   0x54

+#define COUNTER1_COUNT      0x12

+

+//

+// Function Prototypes

+//

+EFI_STATUS

+EFIAPI

+WaitForTick (

+  IN EFI_METRONOME_ARCH_PROTOCOL  *This,

+  IN UINT32                       TickNumber

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  This        - TODO: add argument description

+  TickNumber  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.inf b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.inf
new file mode 100644
index 0000000..572fa90
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/LegacyMetronome/Metronome.inf
@@ -0,0 +1,43 @@
+## @file

+# 

+# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#  Module Name:

+#

+#  Abstract:

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = Metronome

+  FILE_GUID                      = 07A9330A-F347-11d4-9A49-0090273FC14D

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = InstallMetronome

+

+[Packages]

+  MdePkg/MdePkg.dec

+

+[LibraryClasses]

+  UefiDriverEntryPoint

+  DebugLib

+  UefiBootServicesTableLib

+  IoLib

+  

+[Sources]

+  Metronome.c

+  Metronome.h

+

+[Protocols]

+  gEfiMetronomeArchProtocolGuid

+

+[Depex]

+  TRUE

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.c b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.c
new file mode 100644
index 0000000..1875dc9
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.c
@@ -0,0 +1,1731 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  BdsPlatform.c

+

+Abstract:

+

+  This file include all platform action which can be customized

+  by IBV/OEM.

+

+--*/

+

+#include "BdsPlatform.h"

+

+#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)

+

+extern BOOLEAN  gConnectAllHappened;

+extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;

+

+EFI_GUID                    *gTableGuidArray[] = {

+    &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid

+  };

+

+//

+// BDS Platform Functions

+//

+

+VOID

+GetSystemTablesFromHob (

+  VOID

+  )

+/*++

+

+Routine Description:

+  Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables

+

+Arguments:

+  None

+

+Returns:

+  None.

+

+--*/

+{

+  EFI_PEI_HOB_POINTERS        GuidHob;

+  EFI_PEI_HOB_POINTERS        HobStart;

+  EFI_PHYSICAL_ADDRESS        *Table;

+  UINTN                       Index;

+

+  //

+  // Get Hob List

+  //

+  HobStart.Raw = GetHobList ();

+  //

+  // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table

+  //

+  for (Index = 0; Index < sizeof (gTableGuidArray) / sizeof (*gTableGuidArray); ++Index) {

+    GuidHob.Raw = GetNextGuidHob (gTableGuidArray[Index], HobStart.Raw);

+    if (GuidHob.Raw != NULL) {

+      Table = GET_GUID_HOB_DATA (GuidHob.Guid);

+      if (Table != NULL) {

+        //

+        // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,

+        // According to UEFI Spec, we should make sure Smbios table, 

+        // ACPI table and Mps tables kept in memory of specified type

+        //

+        ConvertSystemTable(gTableGuidArray[Index], (VOID**)&Table);

+        gBS->InstallConfigurationTable (gTableGuidArray[Index], (VOID *)Table);

+      }

+    }

+  }

+

+  return ;

+}

+

+#if 0

+VOID

+PrintMemoryMap (

+  VOID

+  )

+{

+  EFI_MEMORY_DESCRIPTOR       *MemMap;

+  EFI_MEMORY_DESCRIPTOR       *MemMapPtr;

+  UINTN                       MemMapSize;

+  UINTN                       MapKey, DescriptorSize;

+  UINTN                       Index;

+  UINT32                      DescriptorVersion;

+  UINT64                      Bytes;

+  EFI_STATUS                  Status;

+

+  MemMapSize = 0;

+  MemMap     = NULL;

+  Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);

+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);

+  MemMapSize += EFI_PAGE_SIZE;

+  Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap);

+  ASSERT (Status == EFI_SUCCESS);

+  Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);

+  ASSERT (Status == EFI_SUCCESS);

+  MemMapPtr = MemMap;

+

+  ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);

+

+  for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) {

+    Bytes = LShiftU64 (MemMap->NumberOfPages, 12);

+    DEBUG ((EFI_D_ERROR, "%lX-%lX  %lX %lX %X\n",

+          MemMap->PhysicalStart, 

+          MemMap->PhysicalStart + Bytes - 1,

+          MemMap->NumberOfPages, 

+          MemMap->Attribute,

+          (UINTN)MemMap->Type));

+    MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize);

+  }

+

+  gBS->FreePool (MemMapPtr);

+}

+#endif

+

+VOID

+UpdateMemoryMap (

+  VOID

+  )

+{

+  EFI_STATUS                      Status;

+  EFI_PEI_HOB_POINTERS            GuidHob;

+  VOID                            *Table;

+  MEMORY_DESC_HOB                 MemoryDescHob;

+  UINTN                           Index;

+  EFI_PHYSICAL_ADDRESS            Memory;

+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;

+  

+  GuidHob.Raw = GetFirstGuidHob (&gLdrMemoryDescriptorGuid);

+  if (GuidHob.Raw == NULL) {

+    DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));

+    return;

+  }

+  Table = GET_GUID_HOB_DATA (GuidHob.Guid);

+  if (Table == NULL) {

+    DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));

+    return;

+  }

+  MemoryDescHob.MemDescCount = *(UINTN *)Table;

+  MemoryDescHob.MemDesc      = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));

+

+  //

+  // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap

+  //

+  for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {

+    if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {

+      continue;

+    }

+    if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000ULL) {

+      continue;

+    }

+    if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||

+        (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||

+        (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||

+        (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||

+        (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {

+      DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%016lx, ", MemoryDescHob.MemDesc[Index].PhysicalStart));

+      DEBUG ((EFI_D_ERROR, "PageNumber    - 0x%016lx, ", MemoryDescHob.MemDesc[Index].NumberOfPages));

+      DEBUG ((EFI_D_ERROR, "Attribute     - 0x%016lx, ", MemoryDescHob.MemDesc[Index].Attribute));

+      DEBUG ((EFI_D_ERROR, "Type          - 0x%08x\n", MemoryDescHob.MemDesc[Index].Type));

+      if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||

+          (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {

+        //

+        // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore.

+        // The memory type is assigned in EfiLdr

+        //

+        Status = gDS->GetMemorySpaceDescriptor (MemoryDescHob.MemDesc[Index].PhysicalStart, &Descriptor);

+        if (EFI_ERROR (Status)) {

+          continue;

+        }

+        if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {

+          //

+          // BFV or tested DXE core

+          //

+          continue;

+        }

+        //

+        // Untested DXE Core region, free and remove

+        //

+        Status = gDS->FreeMemorySpace (

+                        MemoryDescHob.MemDesc[Index].PhysicalStart,

+                        LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT)

+                        );

+        if (EFI_ERROR (Status)) {

+          DEBUG ((EFI_D_ERROR, "FreeMemorySpace fail - %r!\n", Status));

+          continue;

+        }

+        Status = gDS->RemoveMemorySpace (

+                        MemoryDescHob.MemDesc[Index].PhysicalStart,

+                        LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT)

+                        );

+        if (EFI_ERROR (Status)) {

+          DEBUG ((EFI_D_ERROR, "RemoveMemorySpace fail - %r!\n", Status));

+          continue;

+        }

+

+        //

+        // Convert Runtime type to BootTime type

+        //

+        if (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) {

+          MemoryDescHob.MemDesc[Index].Type = EfiBootServicesData;

+        } else {

+          MemoryDescHob.MemDesc[Index].Type = EfiBootServicesCode;

+        }

+

+        //

+        // PassThrough, let below code add and alloate.

+        //

+      }

+      //

+      // ACPI or reserved memory

+      //

+      Status = gDS->AddMemorySpace (

+                      EfiGcdMemoryTypeSystemMemory,

+                      MemoryDescHob.MemDesc[Index].PhysicalStart,

+                      LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),

+                      MemoryDescHob.MemDesc[Index].Attribute

+                      );

+      if (EFI_ERROR (Status)) {

+        DEBUG ((EFI_D_ERROR, "AddMemorySpace fail - %r!\n", Status));

+        if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||

+            (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {

+          //

+          // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.

+          // For EfiReservedMemoryType, there maybe overlap. So skip check here.

+          //

+//          ASSERT_EFI_ERROR (Status);

+        }

+        continue;

+      }

+

+      Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;

+      Status = gBS->AllocatePages (

+                      AllocateAddress,

+                      (EFI_MEMORY_TYPE)MemoryDescHob.MemDesc[Index].Type,

+                      (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,

+                      &Memory

+                      );

+      if (EFI_ERROR (Status)) {

+        DEBUG ((EFI_D_ERROR, "AllocatePages fail - %r!\n", Status));

+        //

+        // For the page added, it must be allocated.

+        //

+//        ASSERT_EFI_ERROR (Status);

+        continue;

+      }

+    }

+  }

+  

+}

+

+EFI_STATUS

+DisableUsbLegacySupport(

+  void

+  )

+/*++

+

+Routine Description:

+  Disabble the USB legacy Support in all Ehci and Uhci.

+  This function assume all PciIo handles have been created in system.

+  

+Arguments:

+  None

+  

+Returns:

+  EFI_SUCCESS

+  EFI_NOT_FOUND

+--*/

+{

+  EFI_STATUS                            Status;

+  EFI_HANDLE                            *HandleArray;

+  UINTN                                 HandleArrayCount;

+  UINTN                                 Index;

+  EFI_PCI_IO_PROTOCOL                   *PciIo;

+  UINT8                                 Class[3];

+  UINT16                                Command;

+  UINT32                                HcCapParams;

+  UINT32                                ExtendCap;

+  UINT32                                Value;

+  UINT32                                TimeOut;

+  

+  //

+  // Find the usb host controller 

+  //   

+  Status = gBS->LocateHandleBuffer (

+                  ByProtocol,

+                  &gEfiPciIoProtocolGuid,

+                  NULL,

+                  &HandleArrayCount,

+                  &HandleArray

+                  );

+  if (!EFI_ERROR (Status)) {

+    for (Index = 0; Index < HandleArrayCount; Index++) {

+      Status = gBS->HandleProtocol (

+                      HandleArray[Index],

+                      &gEfiPciIoProtocolGuid,

+                      (VOID **)&PciIo

+                      );

+      if (!EFI_ERROR (Status)) {

+        //

+        // Find the USB host controller controller

+        //

+        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);

+        if (!EFI_ERROR (Status)) {

+          if ((PCI_CLASS_SERIAL == Class[2]) &&

+              (PCI_CLASS_SERIAL_USB == Class[1])) {

+            if (PCI_IF_UHCI == Class[0]) {

+              //

+              // Found the UHCI, then disable the legacy support

+              //

+              Command = 0;

+              Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command);

+            } else if (PCI_IF_EHCI == Class[0]) {

+              //

+              // Found the EHCI, then disable the legacy support

+              //

+              Status = PciIo->Mem.Read (

+                                   PciIo,

+                                   EfiPciIoWidthUint32,

+                                   0,                   //EHC_BAR_INDEX

+                                   (UINT64) 0x08,       //EHC_HCCPARAMS_OFFSET

+                                   1,

+                                   &HcCapParams

+                                   );

+              

+              ExtendCap = (HcCapParams >> 8) & 0xFF;

+              //

+              // Disable the SMI in USBLEGCTLSTS firstly

+              //

+              PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);

+              Value &= 0xFFFF0000;

+              PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);

+              

+              //

+              // Get EHCI Ownership from legacy bios

+              //

+              PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);

+              Value |= (0x1 << 24);

+              PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);

+

+              TimeOut = 40;

+              while (TimeOut--) {

+                gBS->Stall (500);

+

+                PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);

+

+                if ((Value & 0x01010000) == 0x01000000) {

+                  break;

+                }

+              }

+            }

+          } 

+        }

+      }

+    }

+  } else {

+    return Status;

+  }

+  gBS->FreePool (HandleArray);

+  return EFI_SUCCESS;

+}

+

+

+VOID

+EFIAPI

+PlatformBdsInit (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Platform Bds init. Incude the platform firmware vendor, revision

+  and so crc check.

+

+Arguments:

+

+Returns:

+

+  None.

+

+--*/

+{

+  GetSystemTablesFromHob ();

+

+  UpdateMemoryMap ();

+  

+  //

+  // Append Usb Keyboard short form DevicePath into "ConInDev" 

+  //

+  BdsLibUpdateConsoleVariable (

+    VarConsoleInpDev,

+    (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,

+    NULL

+    );

+}

+

+UINT64

+GetPciExpressBaseAddressForRootBridge (

+  IN UINTN    HostBridgeNumber,

+  IN UINTN    RootBridgeNumber

+  )

+/*++

+

+Routine Description:

+  This routine is to get PciExpress Base Address for this RootBridge

+

+Arguments:

+  HostBridgeNumber - The number of HostBridge

+  RootBridgeNumber - The number of RootBridge

+    

+Returns:

+  UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge

+

+--*/

+{

+  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;

+  UINTN                                    BufferSize;

+  UINT32                                   Index;

+  UINT32                                   Number;

+  EFI_PEI_HOB_POINTERS                     GuidHob;

+

+  //

+  // Get PciExpressAddressInfo Hob

+  //

+  PciExpressBaseAddressInfo = NULL;

+  BufferSize                = 0;

+  GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);

+  if (GuidHob.Raw != NULL) {

+    PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);

+    BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);

+  } else {

+    return 0;

+  }

+

+  //

+  // Search the PciExpress Base Address in the Hob for current RootBridge

+  //

+  Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));

+  for (Index = 0; Index < Number; Index++) {

+    if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&

+        (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {

+      return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;

+    }

+  }

+

+  //

+  // Do not find the PciExpress Base Address in the Hob

+  //

+  return 0;  

+}

+

+VOID

+PatchPciRootBridgeDevicePath (

+  IN UINTN    HostBridgeNumber,

+  IN UINTN    RootBridgeNumber,

+  IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH  *RootBridge

+  )

+{

+  UINT64  PciExpressBase;

+

+  PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);

+  

+  DEBUG ((EFI_D_INFO, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase));

+  

+  if (PciExpressBase != 0) {

+    RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);

+  }

+}

+

+EFI_STATUS

+ConnectRootBridge (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Connect RootBridge

+

+Arguments:

+

+  None.

+ 

+Returns:

+

+  EFI_SUCCESS             - Connect RootBridge successfully.

+  EFI_STATUS              - Connect RootBridge fail.

+

+--*/

+{

+  EFI_STATUS                Status;

+  EFI_HANDLE                RootHandle;

+

+  //

+  // Patch Pci Root Bridge Device Path

+  //

+  PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);

+

+  //

+  // Make all the PCI_IO protocols on PCI Seg 0 show up

+  //

+  BdsLibConnectDevicePath (gPlatformRootBridges[0]);

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiDevicePathProtocolGuid, 

+                  &gPlatformRootBridges[0], 

+                  &RootHandle

+                  );

+  DEBUG ((EFI_D_INFO, "Pci Root bridge handle is 0x%X\n", RootHandle));

+  

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PrepareLpcBridgeDevicePath (

+  IN EFI_HANDLE                DeviceHandle

+  )

+/*++

+

+Routine Description:

+

+  Add IsaKeyboard to ConIn,

+  add IsaSerial to ConOut, ConIn, ErrOut.

+  LPC Bridge: 06 01 00

+

+Arguments:

+

+  DeviceHandle            - Handle of PCIIO protocol.

+ 

+Returns:

+

+  EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.

+  EFI_STATUS              - No LPC bridge is added.

+

+--*/

+{

+  EFI_STATUS                Status;

+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;

+

+  DevicePath = NULL;

+  Status = gBS->HandleProtocol (

+                  DeviceHandle,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID*)&DevicePath

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  TempDevicePath = DevicePath;

+

+  //

+  // Register Keyboard

+  //

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);

+

+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);

+

+  //

+  // Register COM1

+  //

+  DevicePath = TempDevicePath;

+  gPnp16550ComPortDeviceNode.UID = 0;

+

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);

+

+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);

+

+  //

+  // Register COM2

+  //

+  DevicePath = TempDevicePath;

+  gPnp16550ComPortDeviceNode.UID = 1;

+

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);

+

+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+GetGopDevicePath (

+   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,

+   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath

+   )

+{

+  UINTN                           Index;

+  EFI_STATUS                      Status;

+  EFI_HANDLE                      PciDeviceHandle;

+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;

+  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;

+  UINTN                           GopHandleCount;

+  EFI_HANDLE                      *GopHandleBuffer;

+

+  if (PciDevicePath == NULL || GopDevicePath == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  //

+  // Initialize the GopDevicePath to be PciDevicePath

+  //

+  *GopDevicePath    = PciDevicePath;

+  TempPciDevicePath = PciDevicePath;

+

+  Status = gBS->LocateDevicePath (

+                  &gEfiDevicePathProtocolGuid,

+                  &TempPciDevicePath,

+                  &PciDeviceHandle

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Try to connect this handle, so that GOP dirver could start on this 

+  // device and create child handles with GraphicsOutput Protocol installed

+  // on them, then we get device paths of these child handles and select 

+  // them as possible console device.

+  //

+  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);

+

+  Status = gBS->LocateHandleBuffer (

+                  ByProtocol,

+                  &gEfiGraphicsOutputProtocolGuid,

+                  NULL,

+                  &GopHandleCount,

+                  &GopHandleBuffer

+                  );

+  if (!EFI_ERROR (Status)) {

+    //

+    // Add all the child handles as possible Console Device

+    //

+    for (Index = 0; Index < GopHandleCount; Index++) {

+      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);

+      if (EFI_ERROR (Status)) {

+        continue;

+      }

+      if (CompareMem (

+            PciDevicePath,

+            TempDevicePath,

+            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH

+            ) == 0) {

+        //

+        // In current implementation, we only enable one of the child handles

+        // as console device, i.e. sotre one of the child handle's device

+        // path to variable "ConOut"

+        // In futhure, we could select all child handles to be console device

+        //       

+

+        *GopDevicePath = TempDevicePath;

+

+        //

+        // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()

+        // Add the integrity GOP device path.

+        //

+        BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);

+        BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);

+      }

+    }

+    gBS->FreePool (GopHandleBuffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PreparePciVgaDevicePath (

+  IN EFI_HANDLE                DeviceHandle

+  )

+/*++

+

+Routine Description:

+

+  Add PCI VGA to ConOut.

+  PCI VGA: 03 00 00

+

+Arguments:

+

+  DeviceHandle            - Handle of PCIIO protocol.

+ 

+Returns:

+

+  EFI_SUCCESS             - PCI VGA is added to ConOut.

+  EFI_STATUS              - No PCI VGA device is added.

+

+--*/

+{

+  EFI_STATUS                Status;

+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;

+

+  DevicePath    = NULL;

+  GopDevicePath = NULL;

+  Status = gBS->HandleProtocol (

+                  DeviceHandle,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID*)&DevicePath

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  GetGopDevicePath (DevicePath, &GopDevicePath);

+  DevicePath = GopDevicePath;

+

+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PreparePciSerialDevicePath (

+  IN EFI_HANDLE                DeviceHandle

+  )

+/*++

+

+Routine Description:

+

+  Add PCI Serial to ConOut, ConIn, ErrOut.

+  PCI Serial: 07 00 02

+

+Arguments:

+

+  DeviceHandle            - Handle of PCIIO protocol.

+ 

+Returns:

+

+  EFI_SUCCESS             - PCI Serial is added to ConOut, ConIn, and ErrOut.

+  EFI_STATUS              - No PCI Serial device is added.

+

+--*/

+{

+  EFI_STATUS                Status;

+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

+  

+  DevicePath = NULL;

+  Status = gBS->HandleProtocol (

+                  DeviceHandle,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID*)&DevicePath

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);

+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);

+

+  BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);

+  BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+DetectAndPreparePlatformPciDevicePath (

+  BOOLEAN DetectVgaOnly

+  )

+/*++

+

+Routine Description:

+

+  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut

+

+Arguments:

+

+  DetectVgaOnly           - Only detect VGA device if it's TRUE.

+ 

+Returns:

+

+  EFI_SUCCESS             - PCI Device check and Console variable update successfully.

+  EFI_STATUS              - PCI Device check or Console variable update fail.

+

+--*/

+{

+  EFI_STATUS                Status;

+  UINTN                     HandleCount;

+  EFI_HANDLE                *HandleBuffer;

+  UINTN                     Index;

+  EFI_PCI_IO_PROTOCOL       *PciIo;

+  PCI_TYPE00                Pci;

+

+  //

+  // Start to check all the PciIo to find all possible device

+  //

+  HandleCount = 0;

+  HandleBuffer = NULL;

+  Status = gBS->LocateHandleBuffer (

+                  ByProtocol,

+                  &gEfiPciIoProtocolGuid,

+                  NULL,

+                  &HandleCount,

+                  &HandleBuffer

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  for (Index = 0; Index < HandleCount; Index++) {

+    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);

+    if (EFI_ERROR (Status)) {

+      continue;

+    }

+

+    //

+    // Check for all PCI device

+    //

+    Status = PciIo->Pci.Read (

+                      PciIo,

+                      EfiPciIoWidthUint32,

+                      0,

+                      sizeof (Pci) / sizeof (UINT32),

+                      &Pci

+                      );

+    if (EFI_ERROR (Status)) {

+      continue;

+    }

+

+    if (!DetectVgaOnly) {

+      //

+      // Here we decide whether it is LPC Bridge

+      //

+      if ((IS_PCI_LPC (&Pci)) ||

+          ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {

+        //

+        // Add IsaKeyboard to ConIn,

+        // add IsaSerial to ConOut, ConIn, ErrOut

+        //

+        DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));

+        PrepareLpcBridgeDevicePath (HandleBuffer[Index]);

+        continue;

+      }

+      //

+      // Here we decide which Serial device to enable in PCI bus 

+      //

+      if (IS_PCI_16550SERIAL (&Pci)) {

+        //

+        // Add them to ConOut, ConIn, ErrOut.

+        //

+        DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));

+        PreparePciSerialDevicePath (HandleBuffer[Index]);

+        continue;

+      }

+    }

+

+    //

+    // Here we decide which VGA device to enable in PCI bus 

+    //

+    if (IS_PCI_VGA (&Pci)) {

+      //

+      // Add them to ConOut.

+      //

+      DEBUG ((EFI_D_INFO, "Find the VGA device\n"));

+      PreparePciVgaDevicePath (HandleBuffer[Index]);

+      continue;

+    }

+  }

+  

+  gBS->FreePool (HandleBuffer);

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PlatformBdsConnectConsole (

+  IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole

+  )

+/*++

+

+Routine Description:

+

+  Connect the predefined platform default console device. Always try to find

+  and enable the vga device if have.

+

+Arguments:

+

+  PlatformConsole         - Predfined platform default console device array.

+ 

+Returns:

+

+  EFI_SUCCESS             - Success connect at least one ConIn and ConOut 

+                            device, there must have one ConOut device is 

+                            active vga device.

+  

+  EFI_STATUS              - Return the status of 

+                            BdsLibConnectAllDefaultConsoles ()

+

+--*/

+{

+  EFI_STATUS                         Status;

+  UINTN                              Index;

+  EFI_DEVICE_PATH_PROTOCOL           *VarConout;

+  EFI_DEVICE_PATH_PROTOCOL           *VarConin;

+  UINTN                              DevicePathSize;

+

+  //

+  // Connect RootBridge

+  //

+  ConnectRootBridge ();

+

+  VarConout = BdsLibGetVariableAndSize (

+                VarConsoleOut,

+                &gEfiGlobalVariableGuid,

+                &DevicePathSize

+                );

+  VarConin = BdsLibGetVariableAndSize (

+               VarConsoleInp,

+               &gEfiGlobalVariableGuid,

+               &DevicePathSize

+               );

+  

+  if (VarConout == NULL || VarConin == NULL) {

+    //

+    // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut

+    //

+    DetectAndPreparePlatformPciDevicePath (FALSE);

+

+    //

+    // Have chance to connect the platform default console,

+    // the platform default console is the minimue device group

+    // the platform should support

+    //

+    for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {

+      //

+      // Update the console variable with the connect type

+      //

+      if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {

+        BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);

+      }

+      if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {

+        BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);

+      }

+      if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {

+        BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);

+      }

+    }

+  } else {

+    //

+    // Only detect VGA device and add them to ConOut

+    //

+    DetectAndPreparePlatformPciDevicePath (TRUE);

+  }

+  

+  //

+  // The ConIn devices connection will start the USB bus, should disable all

+  // Usb legacy support firstly.

+  // Caution: Must ensure the PCI bus driver has been started. Since the 

+  // ConnectRootBridge() will create all the PciIo protocol, it's safe here now

+  //

+  Status = DisableUsbLegacySupport();

+  

+  //

+  // Connect the all the default console with current cosole variable

+  //

+  Status = BdsLibConnectAllDefaultConsoles ();

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+VOID

+PlatformBdsConnectSequence (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Connect with predeined platform connect sequence, 

+  the OEM/IBV can customize with their own connect sequence.

+  

+Arguments:

+

+  None.

+ 

+Returns:

+

+  None.

+  

+--*/

+{

+  UINTN Index;

+

+  Index = 0;

+

+  //

+  // Here we can get the customized platform connect sequence

+  // Notes: we can connect with new variable which record the

+  // last time boots connect device path sequence

+  //

+  while (gPlatformConnectSequence[Index] != NULL) {

+    //

+    // Build the platform boot option

+    //

+    BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);

+    Index++;

+  }

+

+}

+

+VOID

+PlatformBdsGetDriverOption (

+  IN OUT LIST_ENTRY              *BdsDriverLists

+  )

+/*++

+

+Routine Description:

+

+  Load the predefined driver option, OEM/IBV can customize this

+  to load their own drivers

+  

+Arguments:

+

+  BdsDriverLists  - The header of the driver option link list.

+ 

+Returns:

+

+  None.

+  

+--*/

+{

+  UINTN Index;

+

+  Index = 0;

+

+  //

+  // Here we can get the customized platform driver option

+  //

+  while (gPlatformDriverOption[Index] != NULL) {

+    //

+    // Build the platform boot option

+    //

+    BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");

+    Index++;

+  }

+

+}

+

+VOID

+PlatformBdsDiagnostics (

+  IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,

+  IN BOOLEAN                     QuietBoot,

+  IN BASEM_MEMORY_TEST           BaseMemoryTest

+  )

+/*++

+

+Routine Description:

+

+  Perform the platform diagnostic, such like test memory. OEM/IBV also

+  can customize this fuction to support specific platform diagnostic.

+  

+Arguments:

+

+  MemoryTestLevel  - The memory test intensive level

+  

+  QuietBoot        - Indicate if need to enable the quiet boot

+

+  BaseMemoryTest   - A pointer to BdsMemoryTest()

+ 

+Returns:

+

+  None.

+  

+--*/

+{

+  EFI_STATUS  Status;

+

+  //

+  // Here we can decide if we need to show

+  // the diagnostics screen

+  // Notes: this quiet boot code should be remove

+  // from the graphic lib

+  //

+  if (QuietBoot) {

+    Status = EnableQuietBoot (PcdGetPtr(PcdLogoFile));

+    if (EFI_ERROR (Status)) {

+      DisableQuietBoot ();

+      return;

+    }

+

+    //

+    // Perform system diagnostic

+    //

+    Status = BaseMemoryTest (MemoryTestLevel);

+    if (EFI_ERROR (Status)) {

+      DisableQuietBoot ();

+    }

+

+    return ;

+  }

+  //

+  // Perform system diagnostic

+  //

+  Status = BaseMemoryTest (MemoryTestLevel);

+}

+

+VOID

+EFIAPI

+PlatformBdsPolicyBehavior (

+  IN OUT LIST_ENTRY              *DriverOptionList,

+  IN OUT LIST_ENTRY              *BootOptionList,

+  IN PROCESS_CAPSULES            ProcessCapsules,

+  IN BASEM_MEMORY_TEST           BaseMemoryTest

+  )

+/*++

+

+Routine Description:

+

+  The function will excute with as the platform policy, current policy

+  is driven by boot mode. IBV/OEM can customize this code for their specific

+  policy action.

+  

+Arguments:

+

+  DriverOptionList - The header of the driver option link list

+  

+  BootOptionList   - The header of the boot option link list

+ 

+Returns:

+

+  None.

+  

+--*/

+{

+  EFI_STATUS                         Status;

+  UINT16                             Timeout;

+  EFI_EVENT                          UserInputDurationTime;

+  UINTN                              Index;

+  EFI_INPUT_KEY                      Key;

+  EFI_BOOT_MODE                      BootMode;

+

+  //

+  // Init the time out value

+  //

+  Timeout = PcdGet16 (PcdPlatformBootTimeOut);

+

+  //

+  // Load the driver option as the driver option list

+  //

+  PlatformBdsGetDriverOption (DriverOptionList);

+

+  //

+  // Get current Boot Mode

+  //

+  Status = BdsLibGetBootMode (&BootMode);

+  DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));

+

+  //

+  // Go the different platform policy with different boot mode

+  // Notes: this part code can be change with the table policy

+  //

+  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);

+  //

+  // Connect platform console

+  //

+  Status = PlatformBdsConnectConsole (gPlatformConsole);

+  if (EFI_ERROR (Status)) {

+    //

+    // Here OEM/IBV can customize with defined action

+    //

+    PlatformBdsNoConsoleAction ();

+  }

+  //

+  // Create a 300ms duration event to ensure user has enough input time to enter Setup

+  //

+  Status = gBS->CreateEvent (

+                  EVT_TIMER,

+                  0,

+                  NULL,

+                  NULL,

+                  &UserInputDurationTime

+                  );

+  ASSERT (Status == EFI_SUCCESS);

+  Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);

+  ASSERT (Status == EFI_SUCCESS);

+  //

+  // Memory test and Logo show

+  //

+  PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);

+

+  //

+  // Perform some platform specific connect sequence

+  //

+  PlatformBdsConnectSequence ();

+

+  //

+  // Give one chance to enter the setup if we

+  // have the time out

+  //

+  // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.

+  Timeout = 5;  

+  if (Timeout != 0) {

+    PlatformBdsEnterFrontPage (Timeout, FALSE);

+  }

+

+  //

+  //BdsLibConnectAll ();

+  //BdsLibEnumerateAllBootOption (BootOptionList);  

+  

+  //

+  // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot

+  // checking code in real production tip.

+  //          

+  // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device 

+  // and do enumerate all the default boot options. But in development system board, the boot mode 

+  // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box

+  // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.

+  //

+  Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");

+  if (EFI_ERROR(Status)) {

+    //

+    // If cannot find "BootOrder" variable,  it may be first boot. 

+    // Try to connect all devices and enumerate all boot options here.

+    //

+    BdsLibConnectAll ();

+    BdsLibEnumerateAllBootOption (BootOptionList);

+  } 

+

+  //

+  // To give the User a chance to enter Setup here, if user set TimeOut is 0.

+  // BDS should still give user a chance to enter Setup

+  // Check whether the user input after the duration time has expired 

+  //

+  gBS->WaitForEvent (1, &UserInputDurationTime, &Index);

+  gBS->CloseEvent (UserInputDurationTime);

+  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);

+  

+  if (!EFI_ERROR (Status)) {

+    //

+    // Enter Setup if user input 

+    //

+    Timeout = 0xffff;

+    PlatformBdsEnterFrontPage (Timeout, FALSE);

+  }

+  

+  return ;

+

+}

+

+VOID

+EFIAPI

+PlatformBdsBootSuccess (

+  IN  BDS_COMMON_OPTION *Option

+  )

+/*++

+

+Routine Description:

+  

+  Hook point after a boot attempt succeeds. We don't expect a boot option to

+  return, so the EFI 1.0 specification defines that you will default to an

+  interactive mode and stop processing the BootOrder list in this case. This

+  is alos a platform implementation and can be customized by IBV/OEM.

+

+Arguments:

+

+  Option - Pointer to Boot Option that succeeded to boot.

+

+Returns:

+  

+  None.

+

+--*/

+{

+  CHAR16  *TmpStr;

+

+  //

+  // If Boot returned with EFI_SUCCESS and there is not in the boot device

+  // select loop then we need to pop up a UI and wait for user input.

+  //

+  TmpStr = Option->StatusString;

+  if (TmpStr != NULL) {

+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);

+    gBS->FreePool (TmpStr);

+  }

+}

+

+VOID

+EFIAPI

+PlatformBdsBootFail (

+  IN  BDS_COMMON_OPTION  *Option,

+  IN  EFI_STATUS         Status,

+  IN  CHAR16             *ExitData,

+  IN  UINTN              ExitDataSize

+  )

+/*++

+

+Routine Description:

+  

+  Hook point after a boot attempt fails.

+

+Arguments:

+  

+  Option - Pointer to Boot Option that failed to boot.

+

+  Status - Status returned from failed boot.

+

+  ExitData - Exit data returned from failed boot.

+

+  ExitDataSize - Exit data size returned from failed boot.

+

+Returns:

+  

+  None.

+

+--*/

+{

+  CHAR16  *TmpStr;

+

+  //

+  // If Boot returned with failed status then we need to pop up a UI and wait

+  // for user input.

+  //

+  TmpStr = Option->StatusString;

+  if (TmpStr != NULL) {

+    BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);

+    gBS->FreePool (TmpStr);

+  }

+

+}

+

+EFI_STATUS

+PlatformBdsNoConsoleAction (

+  VOID

+  )

+/*++

+

+Routine Description:

+  

+  This function is remained for IBV/OEM to do some platform action,

+  if there no console device can be connected.

+

+Arguments:

+  

+  None.

+  

+Returns:

+  

+  EFI_SUCCESS      - Direct return success now.

+

+--*/

+{

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+ConvertSystemTable (

+  IN     EFI_GUID        *TableGuid,

+  IN OUT VOID            **Table

+  )

+/*++

+

+Routine Description:

+  Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000

+  Assumption here:

+   As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg, 

+   So here we just check if the range is E/F seg, 

+   and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS

+

+Arguments:

+  TableGuid - Guid of the table

+  Table     - pointer to the table  

+

+Returns:

+  EFI_SUCEESS - Convert Table successfully

+  Other       - Failed

+

+--*/

+{

+  EFI_STATUS      Status;

+  VOID            *AcpiHeader;

+  UINTN           AcpiTableLen;

+  

+  //

+  // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version. 

+  //

+  AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));

+  

+  if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){

+    if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){

+      //

+      // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size

+      //

+      AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);

+    } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){

+      //

+      // If Acpi 2.0 or later, use RSDP Length fied.

+      //

+      AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;

+    } else {

+      //

+      // Invalid Acpi Version, return

+      //

+      return EFI_UNSUPPORTED;

+    }

+    Status = ConvertAcpiTable (AcpiTableLen, Table);

+    return Status; 

+  }

+  

+  //

+  // If matches smbios guid, convert Smbios table.

+  //

+  if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){

+    Status = ConvertSmbiosTable (Table);

+    return Status;

+  }

+  

+  //

+  // If the table is MP table?

+  //

+  if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){

+    Status = ConvertMpsTable (Table);

+    return Status;

+  }

+  

+  return EFI_UNSUPPORTED;

+}  

+

+

+EFI_STATUS

+ConvertAcpiTable (

+  IN     UINTN                       TableLen,

+  IN OUT VOID                        **Table

+  )

+/*++

+

+Routine Description:

+  Convert RSDP of ACPI Table if its location is lower than Address:0x100000

+  Assumption here:

+   As in legacy Bios, ACPI table is required to place in E/F Seg, 

+   So here we just check if the range is E/F seg, 

+   and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS

+

+Arguments:

+  TableLen  - Acpi RSDP length

+  Table     - pointer to the table  

+

+Returns:

+  EFI_SUCEESS - Convert Table successfully

+  Other       - Failed

+

+--*/

+{

+  VOID                  *AcpiTableOri;

+  VOID                  *AcpiTableNew;

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  BufferPtr;

+

+  

+  AcpiTableOri    =  (VOID *)(UINTN)(*(UINT64*)(*Table));

+  if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {

+    BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;

+    Status = gBS->AllocatePages (

+                    AllocateMaxAddress,

+                    EfiACPIMemoryNVS,

+                    EFI_SIZE_TO_PAGES(TableLen),

+                    &BufferPtr

+                    );

+    ASSERT_EFI_ERROR (Status);

+    AcpiTableNew = (VOID *)(UINTN)BufferPtr;

+    CopyMem (AcpiTableNew, AcpiTableOri, TableLen);

+  } else {

+    AcpiTableNew = AcpiTableOri;

+  }

+  //

+  // Change configuration table Pointer

+  //

+  *Table = AcpiTableNew;

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+ConvertSmbiosTable (

+  IN OUT VOID        **Table

+  )

+/*++

+

+Routine Description:

+

+  Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000

+  Assumption here:

+   As in legacy Bios, Smbios table is required to place in E/F Seg, 

+   So here we just check if the range is F seg, 

+   and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData

+Arguments:

+  Table     - pointer to the table

+

+Returns:

+  EFI_SUCEESS - Convert Table successfully

+  Other       - Failed

+

+--*/

+{

+  SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;

+  SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;

+  EFI_STATUS               Status;

+  UINT32                   SmbiosEntryLen;

+  UINT32                   BufferLen;

+  EFI_PHYSICAL_ADDRESS     BufferPtr;

+  

+  SmbiosTableNew  = NULL;

+  SmbiosTableOri  = NULL;

+  

+  //

+  // Get Smibos configuration Table 

+  //

+  SmbiosTableOri =  (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));

+  

+  if ((SmbiosTableOri == NULL) ||

+      ((UINTN)SmbiosTableOri > 0x100000) ||

+      ((UINTN)SmbiosTableOri < 0xF0000)){

+    return EFI_SUCCESS;

+  }

+  //

+  // Relocate the Smibos memory

+  //

+  BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;

+  if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {

+    SmbiosEntryLen  = SmbiosTableOri->EntryPointLength;

+  } else {

+    //

+    // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1

+    //

+    SmbiosEntryLen = 0x1F;

+  }

+  BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;

+  Status = gBS->AllocatePages (

+                  AllocateMaxAddress,

+                  EfiACPIMemoryNVS,

+                  EFI_SIZE_TO_PAGES(BufferLen),

+                  &BufferPtr

+                  );

+  ASSERT_EFI_ERROR (Status);

+  SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;

+  CopyMem (

+    SmbiosTableNew, 

+    SmbiosTableOri,

+    SmbiosEntryLen

+    );

+  // 

+  // Get Smbios Structure table address, and make sure the start address is 32-bit align

+  //

+  BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);

+  CopyMem (

+    (VOID *)(UINTN)BufferPtr, 

+    (VOID *)(UINTN)(SmbiosTableOri->TableAddress),

+    SmbiosTableOri->TableLength

+    );

+  SmbiosTableNew->TableAddress = (UINT32)BufferPtr;

+  SmbiosTableNew->IntermediateChecksum = 0;

+  SmbiosTableNew->IntermediateChecksum = 

+          CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);

+  //

+  // Change the SMBIOS pointer

+  //

+  *Table = SmbiosTableNew;

+  

+  return EFI_SUCCESS;  

+} 

+

+EFI_STATUS

+ConvertMpsTable (

+  IN OUT VOID          **Table

+  )

+/*++

+

+Routine Description:

+

+  Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000

+  Assumption here:

+   As in legacy Bios, MP table is required to place in E/F Seg, 

+   So here we just check if the range is E/F seg, 

+   and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData

+Arguments:

+  Table     - pointer to the table

+

+Returns:

+  EFI_SUCEESS - Convert Table successfully

+  Other       - Failed

+

+--*/

+{

+  UINT32                                       Data32;

+  UINT32                                       FPLength;

+  EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerOri;

+  EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerNew;

+  EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableOri;

+  EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableNew;

+  VOID                                         *OemTableOri;

+  VOID                                         *OemTableNew;

+  EFI_STATUS                                   Status;

+  EFI_PHYSICAL_ADDRESS                         BufferPtr;

+  

+  //

+  // Get MP configuration Table 

+  //

+  MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));

+  if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) && 

+        ((UINTN)MpsFloatingPointerOri >= 0xF0000))){

+    return EFI_SUCCESS;

+  }

+  //

+  // Get Floating pointer structure length

+  //

+  FPLength = MpsFloatingPointerOri->Length * 16;

+  Data32   = FPLength + SYS_TABLE_PAD (FPLength);

+  MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);

+  if (MpsTableOri != NULL) {

+    Data32 += MpsTableOri->BaseTableLength;

+    Data32 += MpsTableOri->ExtendedTableLength;

+    if (MpsTableOri->OemTablePointer != 0x00) {

+      Data32 += SYS_TABLE_PAD (Data32);

+      Data32 += MpsTableOri->OemTableSize;

+    }

+  } else {

+    return EFI_SUCCESS;

+  }

+  //

+  // Relocate memory

+  //

+  BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;

+  Status = gBS->AllocatePages (

+                  AllocateMaxAddress,

+                  EfiACPIMemoryNVS,

+                  EFI_SIZE_TO_PAGES(Data32),

+                  &BufferPtr

+                  );

+  ASSERT_EFI_ERROR (Status); 

+  MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;

+  CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);

+  //

+  // If Mp Table exists

+  //

+  if (MpsTableOri != NULL) {

+    //

+    // Get Mps table length, including Ext table

+    //

+    BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);

+    MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;

+    CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);

+    

+    if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){

+        BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;

+        BufferPtr += SYS_TABLE_PAD (BufferPtr);

+        OemTableNew = (VOID *)(UINTN)BufferPtr;

+        OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;

+        CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);

+        MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;

+    }

+    MpsTableNew->Checksum = 0;

+    MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength);

+    MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;

+    MpsFloatingPointerNew->Checksum = 0;

+    MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength);

+  }

+  //

+  // Change the pointer

+  //

+  *Table = MpsFloatingPointerNew;

+  

+  return EFI_SUCCESS;  

+} 

+  

+/**

+  Lock the ConsoleIn device in system table. All key

+  presses will be ignored until the Password is typed in. The only way to

+  disable the password is to type it in to a ConIn device.

+

+  @param  Password        Password used to lock ConIn device.

+

+  @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.

+  @retval EFI_UNSUPPORTED Password not found

+

+**/

+EFI_STATUS

+EFIAPI

+LockKeyboards (

+  IN  CHAR16    *Password

+  )

+{

+    return EFI_UNSUPPORTED;

+}

+

+/**

+  This function locks platform flash that is not allowed to be updated during normal boot path.

+  The flash layout is platform specific.

+

+  **/

+VOID

+EFIAPI

+PlatformBdsLockNonUpdatableFlash (

+  VOID

+  )

+{

+  return;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.h b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.h
new file mode 100644
index 0000000..4abb7b7
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/BdsPlatform.h
@@ -0,0 +1,288 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name: 

+

+  BdsPlatform.h

+

+Abstract:

+

+  Head file for BDS Platform specific code

+

+--*/

+

+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_

+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_

+

+

+#include <PiDxe.h>

+

+#include <IndustryStandard/Pci.h>

+#include <IndustryStandard/Acpi.h>

+#include <IndustryStandard/SmBios.h>

+#include <IndustryStandard/LegacyBiosMpTable.h>

+

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseLib.h>

+#include <Library/PcdLib.h>

+#include <Library/GenericBdsLib.h>

+#include <Library/PlatformBdsLib.h>

+#include <Library/HobLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/DevicePathLib.h>

+

+#include <Protocol/PciIo.h>

+

+#include <Guid/Acpi.h>

+#include <Guid/SmBios.h>

+#include <Guid/Mps.h>

+#include <Guid/HobList.h>

+#include <Guid/PciExpressBaseAddress.h>

+#include <Guid/GlobalVariable.h>

+#include <Guid/LdrMemoryDescriptor.h>

+

+extern BDS_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];

+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];

+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformDriverOption[];

+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformRootBridges[];

+extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;

+extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;

+extern UART_DEVICE_PATH           gUartDeviceNode;

+extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;

+//

+//

+//

+#define VarConsoleInpDev        L"ConInDev"

+#define VarConsoleInp           L"ConIn"

+#define VarConsoleOutDev        L"ConOutDev"

+#define VarConsoleOut           L"ConOut"

+#define VarErrorOutDev          L"ErrOutDev"

+#define VarErrorOut             L"ErrOut"

+

+#define PCI_DEVICE_PATH_NODE(Func, Dev) \

+  { \

+    { \

+      HARDWARE_DEVICE_PATH, \

+      HW_PCI_DP, \

+      { \

+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \

+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \

+      } \

+    }, \

+    (Func), \

+    (Dev) \

+  }

+

+#define PNPID_DEVICE_PATH_NODE(PnpId) \

+  { \

+    { \

+      ACPI_DEVICE_PATH, \

+      ACPI_DP, \

+      { \

+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \

+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \

+      } \

+    }, \

+    EISA_PNP_ID((PnpId)), \

+    0 \

+  }

+

+#define gPciRootBridge \

+  PNPID_DEVICE_PATH_NODE(0x0A03)

+

+#define gPciIsaBridge \

+  PCI_DEVICE_PATH_NODE(0, 0x1f)

+

+#define gP2PBridge \

+  PCI_DEVICE_PATH_NODE(0, 0x1e)

+

+#define gPnpPs2Keyboard \

+  PNPID_DEVICE_PATH_NODE(0x0303)

+

+#define gPnp16550ComPort \

+  PNPID_DEVICE_PATH_NODE(0x0501)

+

+#define gUart \

+  { \

+    { \

+      MESSAGING_DEVICE_PATH, \

+      MSG_UART_DP, \

+      { \

+        (UINT8) (sizeof (UART_DEVICE_PATH)), \

+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \

+      } \

+    }, \

+    0, \

+    115200, \

+    8, \

+    1, \

+    1 \

+  }

+

+#define gPcAnsiTerminal \

+  { \

+    { \

+      MESSAGING_DEVICE_PATH, \

+      MSG_VENDOR_DP, \

+      { \

+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \

+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \

+      } \

+    }, \

+    DEVICE_PATH_MESSAGING_PC_ANSI \

+  }

+

+#define gEndEntire \

+  { \

+    END_DEVICE_PATH_TYPE, \

+    END_ENTIRE_DEVICE_PATH_SUBTYPE, \

+    { \

+      END_DEVICE_PATH_LENGTH, \

+      0 \

+    } \

+  }

+

+#define PCI_CLASS_SCC          0x07

+#define PCI_SUBCLASS_SERIAL    0x00

+#define PCI_IF_16550           0x02

+#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)

+

+#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF

+#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )

+//

+// Platform Root Bridge

+//

+typedef struct {

+  ACPI_HID_DEVICE_PATH      PciRootBridge;

+  EFI_DEVICE_PATH_PROTOCOL  End;

+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;

+

+typedef struct {

+  ACPI_HID_DEVICE_PATH      PciRootBridge;

+  PCI_DEVICE_PATH           IsaBridge;

+  ACPI_HID_DEVICE_PATH      Keyboard;

+  EFI_DEVICE_PATH_PROTOCOL  End;

+} PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH;

+

+typedef struct {

+  ACPI_HID_DEVICE_PATH      PciRootBridge;

+  PCI_DEVICE_PATH           IsaBridge;

+  ACPI_HID_DEVICE_PATH      IsaSerial;

+  UART_DEVICE_PATH          Uart;

+  VENDOR_DEVICE_PATH        TerminalType;

+  EFI_DEVICE_PATH_PROTOCOL  End;

+} PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH;

+

+typedef struct {

+  ACPI_HID_DEVICE_PATH      PciRootBridge;

+  PCI_DEVICE_PATH           VgaDevice;

+  EFI_DEVICE_PATH_PROTOCOL  End;

+} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;

+

+typedef struct {

+  ACPI_HID_DEVICE_PATH      PciRootBridge;

+  PCI_DEVICE_PATH           PciBridge;

+  PCI_DEVICE_PATH           SerialDevice;

+  UART_DEVICE_PATH          Uart;

+  VENDOR_DEVICE_PATH        TerminalType;

+  EFI_DEVICE_PATH_PROTOCOL  End;

+} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;

+

+//

+// the short form device path for Usb keyboard

+//

+#define CLASS_HID           3

+#define SUBCLASS_BOOT       1

+#define PROTOCOL_KEYBOARD   1

+

+typedef struct {

+  USB_CLASS_DEVICE_PATH           UsbClass;

+  EFI_DEVICE_PATH_PROTOCOL        End;

+} USB_CLASS_FORMAT_DEVICE_PATH;  

+

+extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH  gPlatformRootBridge0;

+

+//

+// Platform BDS Functions

+//

+VOID

+PlatformBdsGetDriverOption (

+  IN LIST_ENTRY               *BdsDriverLists

+  );

+

+EFI_STATUS

+BdsMemoryTest (

+  EXTENDMEM_COVERAGE_LEVEL Level

+  );

+

+EFI_STATUS

+PlatformBdsShowProgress (

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,

+  CHAR16                        *Title,

+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,

+  UINTN                         Progress,

+  UINTN                         PreviousValue

+  );

+

+VOID

+PlatformBdsConnectSequence (

+  VOID

+  );

+

+EFI_STATUS

+ProcessCapsules (

+  EFI_BOOT_MODE BootMode

+  );

+

+EFI_STATUS

+PlatformBdsConnectConsole (

+  IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole

+  );

+

+EFI_STATUS

+PlatformBdsNoConsoleAction (

+  VOID

+  );

+

+EFI_STATUS

+ConvertMpsTable (

+  IN OUT  VOID     **Table

+  );

+  

+EFI_STATUS

+ConvertSmbiosTable (

+  IN OUT VOID       **Table

+  );

+  

+EFI_STATUS

+ConvertAcpiTable (

+ IN      UINTN      TableLen,

+ IN OUT  VOID       **Table

+  );

+

+EFI_STATUS

+ConvertSystemTable (

+ IN     EFI_GUID   *TableGuid,

+ IN OUT VOID       **Table

+  );

+

+VOID

+PlatformBdsEnterFrontPage (

+  IN UINT16                 TimeoutDefault,

+  IN BOOLEAN                ConnectAllHappened

+  );

+

+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformBds.inf b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformBds.inf
new file mode 100644
index 0000000..f50a62e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformBds.inf
@@ -0,0 +1,65 @@
+## @file

+#

+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+# 

+#  Module Name:

+#

+#    PlatformBds.inf

+#

+#  Abstract:

+#

+#    Component description file for Bds module.

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = DuetBds

+  FILE_GUID                      = A6F691AC-31C8-4444-854C-E2C1A6950F92

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = PlatformBdsLib|DXE_DRIVER   

+

+[Sources]

+  BdsPlatform.c

+  PlatformData.c

+  BdsPlatform.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  DuetPkg/DuetPkg.dec

+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec

+  

+[LibraryClasses]

+  BaseLib

+  MemoryAllocationLib

+  UefiBootServicesTableLib

+  BaseMemoryLib

+  DebugLib

+  PcdLib

+  GenericBdsLib

+  HobLib

+  UefiLib

+  DevicePathLib

+

+[Guids]

+  gEfiGlobalVariableGuid

+  gEfiPciExpressBaseAddressGuid

+  gEfiAcpi20TableGuid

+  gEfiMpsTableGuid

+  gEfiSmbiosTableGuid

+  gEfiAcpiTableGuid

+  gLdrMemoryDescriptorGuid

+  

+[Pcd]

+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut  

+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile  

+  

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformData.c b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformData.c
new file mode 100644
index 0000000..d38f1b4
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetBdsLib/PlatformData.c
@@ -0,0 +1,161 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name: 

+

+  PlatformData.c

+

+Abstract:

+  

+  Defined the platform specific device path which will be used by

+  platform Bbd to perform the platform policy connect.

+

+--*/

+

+#include "BdsPlatform.h"

+

+//

+// Predefined platform default time out value

+//

+UINT16   gPlatformBootTimeOutDefault = 3;

+

+ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;

+ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode = gPnp16550ComPort;

+UART_DEVICE_PATH           gUartDeviceNode            = gUart;

+VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;

+

+//

+// Predefined platform root bridge

+//

+PLATFORM_ROOT_BRIDGE_DEVICE_PATH  gPlatformRootBridge0 = {

+  gPciRootBridge,

+  gEndEntire

+};

+

+EFI_DEVICE_PATH_PROTOCOL          *gPlatformRootBridges[] = {

+  (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,

+  NULL

+};

+

+USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath = {

+  {

+    {

+      MESSAGING_DEVICE_PATH,

+      MSG_USB_CLASS_DP,

+      {

+        (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),

+        (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)

+      }

+    },

+    0xffff,           // VendorId 

+    0xffff,           // ProductId 

+    CLASS_HID,        // DeviceClass 

+    SUBCLASS_BOOT,    // DeviceSubClass

+    PROTOCOL_KEYBOARD // DeviceProtocol

+  },

+

+  { 

+    END_DEVICE_PATH_TYPE, 

+    END_ENTIRE_DEVICE_PATH_SUBTYPE, 

+    {

+      END_DEVICE_PATH_LENGTH, 

+      0

+    }

+  }

+};

+

+/*

+//

+// Platform specific Dummy ISA keyboard device path

+//

+PLATFORM_DUMMY_ISA_KEYBOARD_DEVICE_PATH     gDummyIsaKeyboardDevicePath = {

+  gPciRootBridge,

+  gPciIsaBridge,

+  gPnpPs2Keyboard,

+  gEndEntire

+};

+

+//

+// Platform specific Dummy ISA serial device path

+//

+PLATFORM_DUMMY_ISA_SERIAL_DEVICE_PATH   gDummyIsaSerialDevicePath = {

+  gPciRootBridge,

+  gPciIsaBridge,

+  gPnp16550ComPort,

+  gUart,

+  gPcAnsiTerminal,

+  gEndEntire

+};

+

+//

+// Platform specific Dummy PCI VGA device path

+//

+PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH gDummyPciVgaDevicePath = {

+  gPciRootBridge,

+  PCI_DEVICE_PATH_NODE(0, 0x2),

+  gEndEntire

+};

+

+//

+// Platform specific Dummy PCI serial device path

+//

+PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH gDummyPciSerialDevicePath = {

+  gPciRootBridge,

+  gP2PBridge,

+  PCI_DEVICE_PATH_NODE(0, 0x0),

+  gUart,

+  gPcAnsiTerminal,

+  gEndEntire

+};

+*/

+//

+// Predefined platform default console device path

+//

+BDS_CONSOLE_CONNECT_ENTRY         gPlatformConsole[] = {

+  //

+  // need update dynamically

+  //

+//  {

+//    (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaSerialDevicePath,

+//    (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)

+//  },

+//  {

+//    (EFI_DEVICE_PATH_PROTOCOL *) &gDummyIsaKeyboardDevicePath,

+//    (CONSOLE_IN | STD_ERROR)

+//  },

+//  {

+//    (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciVgaDevicePath,

+//    CONSOLE_OUT

+//  },

+//  {

+//    (EFI_DEVICE_PATH_PROTOCOL *) &gDummyPciSerialDevicePath,

+//    (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)

+//  },

+  {

+    (EFI_DEVICE_PATH_PROTOCOL*) &gUsbClassKeyboardDevicePath, 

+    CONSOLE_IN

+  },

+  {

+    NULL,

+    0

+  }

+};

+

+//

+// Predefined platform specific driver option

+//

+EFI_DEVICE_PATH_PROTOCOL    *gPlatformDriverOption[] = { NULL };

+

+//

+// Predefined platform connect sequence

+//

+EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };

+

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf b/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf
new file mode 100644
index 0000000..b9bac9a
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/DuetTimerLib.inf
@@ -0,0 +1,54 @@
+## @file

+# Timer Library implementation for Boot Timer moudles that require timer services.

+#

+# Timer Library that uses CPU resources to provide calibrated

+#  delays on IA-32 and x64, and uses ITC on IPF. Note: Because CpuLocalApci

+#  and ITC could be programmed by OS, it cannot be used by SMM drivers

+#  and runtime drivers, ACPI timer is recommended for SMM drivers and RUNTIME

+#  drivers.

+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = DuetTimerLib

+  FILE_GUID                      = 5F9A01F5-726E-4f59-809D-887F4766734E

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = TimerLib

+

+

+#

+#  VALID_ARCHITECTURES           = IA32 X64

+#

+

+[Sources.Ia32]

+  X86TimerLib.c

+

+[Sources.X64]

+  X86TimerLib.c

+

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[LibraryClasses]

+  BaseLib

+  DebugLib

+  HobLib

+  IoLib

+  

+[Guids]

+  gEfiAcpiDescriptionGuid

+  

+  

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/X86TimerLib.c b/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/X86TimerLib.c
new file mode 100644
index 0000000..ca3890c
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DuetTimerLib/X86TimerLib.c
@@ -0,0 +1,281 @@
+/** @file

+  Timer Library functions built upon ACPI on IA32/x64.

+  

+  ACPI power management timer is a 24-bit or 32-bit fixed rate free running count-up

+  timer that runs off a 3.579545 MHz clock. 

+  When startup, Duet will check the FADT to determine whether the PM timer is a 

+  32-bit or 24-bit timer.

+

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

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include <Base.h>

+#include <Library/TimerLib.h>

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/HobLib.h>

+#include <Guid/AcpiDescription.h>

+#include <Library/IoLib.h>

+#include <Library/PciLib.h>

+

+EFI_ACPI_DESCRIPTION *gAcpiDesc          = NULL;

+

+/**

+  Internal function to get Acpi information from HOB.

+  

+  @return Pointer to ACPI description structure.

+**/

+EFI_ACPI_DESCRIPTION*

+InternalGetApciDescrptionTable (

+  VOID

+  )

+{

+  EFI_PEI_HOB_POINTERS  GuidHob;

+  

+  if (gAcpiDesc != NULL) {

+    return gAcpiDesc;

+  }

+  

+  GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);

+  if (GuidHob.Raw != NULL) {

+    gAcpiDesc = GET_GUID_HOB_DATA (GuidHob.Guid);

+    DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.RegisterBitWidth = 0x%X\n", gAcpiDesc->PM_TMR_BLK.RegisterBitWidth));

+    DEBUG ((EFI_D_INFO, "ACPI Timer: PM_TMR_BLK.Address = 0x%X\n", gAcpiDesc->PM_TMR_BLK.Address));

+    return gAcpiDesc;

+  } else {

+    DEBUG ((EFI_D_ERROR, "Fail to get Acpi description table from hob\n"));

+    return NULL;

+  }

+}

+

+/**

+  Internal function to read the current tick counter of ACPI.

+

+  @return The tick counter read.

+

+**/

+STATIC

+UINT32

+InternalAcpiGetTimerTick (

+  VOID

+  )

+{

+  return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address);

+}

+

+/**

+  Stalls the CPU for at least the given number of ticks.

+

+  Stalls the CPU for at least the given number of ticks. It's invoked by

+  MicroSecondDelay() and NanoSecondDelay().

+

+  @param  Delay     A period of time to delay in ticks.

+

+**/

+STATIC

+VOID

+InternalAcpiDelay (

+  IN      UINT32                    Delay

+  )

+{

+  UINT32                            Ticks;

+  UINT32                            Times;

+

+  Times    = Delay >> (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);

+  Delay   &= (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2)) - 1;

+  do {

+    //

+    // The target timer count is calculated here

+    //

+    Ticks    = InternalAcpiGetTimerTick () + Delay;

+    Delay    = 1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 2);

+    //

+    // Wait until time out

+    // Delay >= 2^23 (if ACPI provide 24-bit timer) or Delay >= 2^31 (if ACPI

+    // provide 32-bit timer) could not be handled by this function

+    // Timer wrap-arounds are handled correctly by this function

+    //

+    while (((Ticks - InternalAcpiGetTimerTick ()) & (1 << (gAcpiDesc->PM_TMR_BLK.RegisterBitWidth - 1))) == 0) {

+      CpuPause ();

+    }

+  } while (Times-- > 0);

+}

+

+/**

+  Stalls the CPU for at least the given number of microseconds.

+

+  Stalls the CPU for the number of microseconds specified by MicroSeconds.

+

+  @param  MicroSeconds  The minimum number of microseconds to delay.

+

+  @return MicroSeconds

+

+**/

+UINTN

+EFIAPI

+MicroSecondDelay (

+  IN      UINTN                     MicroSeconds

+  )

+{

+

+  if (InternalGetApciDescrptionTable() == NULL) {

+    return MicroSeconds;

+  }

+ 

+  InternalAcpiDelay (

+    (UINT32)DivU64x32 (

+              MultU64x32 (

+                MicroSeconds,

+                3579545

+                ),

+              1000000u

+              )

+    );

+  return MicroSeconds;

+}

+

+/**

+  Stalls the CPU for at least the given number of nanoseconds.

+

+  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.

+

+  @param  NanoSeconds The minimum number of nanoseconds to delay.

+

+  @return NanoSeconds

+

+**/

+UINTN

+EFIAPI

+NanoSecondDelay (

+  IN      UINTN                     NanoSeconds

+  )

+{

+  if (InternalGetApciDescrptionTable() == NULL) {

+    return NanoSeconds;

+  }

+  

+  InternalAcpiDelay (

+    (UINT32)DivU64x32 (

+              MultU64x32 (

+                NanoSeconds,

+                3579545

+                ),

+              1000000000u

+              )

+    );

+  return NanoSeconds;

+}

+

+/**

+  Retrieves the current value of a 64-bit free running performance counter.

+

+  Retrieves the current value of a 64-bit free running performance counter. The

+  counter can either count up by 1 or count down by 1. If the physical

+  performance counter counts by a larger increment, then the counter values

+  must be translated. The properties of the counter can be retrieved from

+  GetPerformanceCounterProperties().

+

+  @return The current value of the free running performance counter.

+

+**/

+UINT64

+EFIAPI

+GetPerformanceCounter (

+  VOID

+  )

+{

+  if (InternalGetApciDescrptionTable() == NULL) {

+    return 0;

+  }

+  

+  return (UINT64)InternalAcpiGetTimerTick ();

+}

+

+/**

+  Retrieves the 64-bit frequency in Hz and the range of performance counter

+  values.

+

+  If StartValue is not NULL, then the value that the performance counter starts

+  with immediately after is it rolls over is returned in StartValue. If

+  EndValue is not NULL, then the value that the performance counter end with

+  immediately before it rolls over is returned in EndValue. The 64-bit

+  frequency of the performance counter in Hz is always returned. If StartValue

+  is less than EndValue, then the performance counter counts up. If StartValue

+  is greater than EndValue, then the performance counter counts down. For

+  example, a 64-bit free running counter that counts up would have a StartValue

+  of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter

+  that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.

+

+  @param  StartValue  The value the performance counter starts with when it

+                      rolls over.

+  @param  EndValue    The value that the performance counter ends with before

+                      it rolls over.

+

+  @return The frequency in Hz.

+

+**/

+UINT64

+EFIAPI

+GetPerformanceCounterProperties (

+  OUT      UINT64                    *StartValue,  OPTIONAL

+  OUT      UINT64                    *EndValue     OPTIONAL

+  )

+{

+  if (InternalGetApciDescrptionTable() == NULL) {

+    return 0;

+  }

+  

+  if (StartValue != NULL) {

+    *StartValue = 0;

+  }

+

+  if (EndValue != NULL) {

+    *EndValue = (1 << gAcpiDesc->PM_TMR_BLK.RegisterBitWidth) - 1;

+  }

+

+  return 3579545;

+}

+

+/**

+  Converts elapsed ticks of performance counter to time in nanoseconds.

+

+  This function converts the elapsed ticks of running performance counter to

+  time value in unit of nanoseconds.

+

+  @param  Ticks     The number of elapsed ticks of running performance counter.

+

+  @return The elapsed time in nanoseconds.

+

+**/

+UINT64

+EFIAPI

+GetTimeInNanoSecond (

+  IN      UINT64                     Ticks

+  )

+{

+  UINT64  NanoSeconds;

+  UINT32  Remainder;

+

+  //

+  //          Ticks

+  // Time = --------- x 1,000,000,000

+  //        Frequency

+  //

+  NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, 3579545, &Remainder), 1000000000u);

+

+  //

+  // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)

+  // will not overflow 64-bit.

+  //

+  NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), 3579545);

+

+  return NanoSeconds;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeCoreReportStatusCodeLibFromHob.inf b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeCoreReportStatusCodeLibFromHob.inf
new file mode 100644
index 0000000..9b4649c
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeCoreReportStatusCodeLibFromHob.inf
@@ -0,0 +1,63 @@
+## @file

+#  Report status code library for DxeCore.

+#

+#  DXE core report status code library that retrieves the status code function from

+#  a GUIDed HOB and installs report status code protocol for later DXE phase drivers.

+#

+#  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>

+#

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution. The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = DxeCoreReportStatusCodeLibFromHob

+  FILE_GUID                      = 5c7f8702-838f-43df-91e6-7833b6f2a067

+  MODULE_TYPE                    = DXE_CORE

+  VERSION_STRING                 = 1.0

+  LIBRARY_CLASS                  = ReportStatusCodeLib|DXE_CORE

+

+  CONSTRUCTOR                    = DxeCoreReportStatusCodeFromHobLibConstructor

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC

+#

+

+[Sources]

+  ReportStatusCodeLib.c

+  DxeSupport.c

+  ReportStatusCodeLibInternal.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+

+[LibraryClasses]

+  PcdLib

+  BaseMemoryLib

+  BaseLib

+  UefiBootServicesTableLib

+  DebugLib

+  DevicePathLib

+  HobLib

+  

+[Guids]

+  gEfiStatusCodeSpecificDataGuid

+  gEfiStatusCodeDataTypeDebugGuid

+

+

+[Protocols]

+  gEfiStatusCodeRuntimeProtocolGuid             # PRODUCES

+

+[Pcd]

+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask

+

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeSupport.c b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeSupport.c
new file mode 100644
index 0000000..36b4025
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/DxeSupport.c
@@ -0,0 +1,177 @@
+/** @file

+  Report Status Code Library that depends on a GUIDed HOB for report status

+  code functionality.

+

+  Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "ReportStatusCodeLibInternal.h"

+

+//

+// Handle to install report status code protocol interface

+//

+EFI_HANDLE               mHandle = NULL;

+

+//

+// Report status protocol interface.

+//

+EFI_STATUS_CODE_PROTOCOL mStatusProtocol = {

+  NULL

+};

+

+/**

+  Initializes report status code infrastructure for DXE phase.

+

+  The constructor function assumes the PEI phase has published the GUIDed HOB

+  tagged by gEfiStatusCodeRuntimeProtocolGuid and publish status code runtime

+  protocol based on the GUID data. It will ASSERT() if one of these operations

+  fails and it will always return EFI_SUCCESS.

+

+  @param  ImageHandle   The firmware allocated handle for the EFI image.

+  @param  SystemTable   A pointer to the EFI System Table.

+

+  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.

+

+**/

+EFI_STATUS

+EFIAPI

+DxeCoreReportStatusCodeFromHobLibConstructor (

+  IN EFI_HANDLE        ImageHandle,

+  IN EFI_SYSTEM_TABLE  *SystemTable

+  )

+{

+  EFI_STATUS           Status;

+  EFI_HOB_GUID_TYPE    *GuidHob;

+

+  GuidHob = GetFirstGuidHob(&gEfiStatusCodeRuntimeProtocolGuid);

+  ASSERT (GuidHob != NULL);

+  

+  mStatusProtocol.ReportStatusCode = (EFI_REPORT_STATUS_CODE) (*(UINTN *) GET_GUID_HOB_DATA (GuidHob));

+  ASSERT (mStatusProtocol.ReportStatusCode != NULL);

+

+  //

+  // Install report status protocol interface so that later DXE phase drivers can retrieve the protocol

+  // interface to report status code.

+  //

+  Status = gBS->InstallProtocolInterface (

+                  &mHandle,

+                  &gEfiStatusCodeRuntimeProtocolGuid,

+                  EFI_NATIVE_INTERFACE,

+                  &mStatusProtocol

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

+

+/**

+  Reports a status code with full parameters.

+

+  The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize

+  is 0, then an extended data buffer is not reported.  If ExtendedData is not

+  NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.

+  ExtendedData is assumed not have the standard status code header, so this function

+  is responsible for allocating a buffer large enough for the standard header and

+  the extended data passed into this function.  The standard header is filled in

+  with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a

+  GUID of gEfiStatusCodeSpecificDatauid is used.  The status code is reported with

+  an instance specified by Instance and a caller ID specified by CallerId.  If

+  CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.

+

+  ReportStatusCodeEx()must actively prevent recursion.  If ReportStatusCodeEx()

+  is called while processing another any other Report Status Code Library function,

+  then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.

+

+  If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().

+  If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  Instance          Status code instance number.

+  @param  CallerId          Pointer to a GUID that identifies the caller of this

+                            function.  If this parameter is NULL, then a caller

+                            ID of gEfiCallerIdGuid is used.

+  @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.

+                            If this parameter is NULL, then a the status code

+                            standard header is filled in with

+                            gEfiStatusCodeSpecificDataGuid.

+  @param  ExtendedData      Pointer to the extended data buffer.  This is an

+                            optional parameter that may be NULL.

+  @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.

+

+  @retval  EFI_SUCCESS           The status code was reported.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate

+                                 the extended data section if it was specified.

+  @retval  EFI_UNSUPPORTED       Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+InternalReportStatusCodeEx (

+  IN EFI_STATUS_CODE_TYPE   Type,

+  IN EFI_STATUS_CODE_VALUE  Value,

+  IN UINT32                 Instance,

+  IN CONST EFI_GUID         *CallerId          OPTIONAL,

+  IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,

+  IN CONST VOID             *ExtendedData      OPTIONAL,

+  IN UINTN                  ExtendedDataSize

+  )

+{

+  EFI_STATUS            Status;

+  EFI_STATUS_CODE_DATA  *StatusCodeData;

+

+  ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0)));

+  ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0)));

+

+  if (gBS == NULL) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Allocate space for the Status Code Header and its buffer

+  //

+  StatusCodeData = NULL;

+  gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData);

+  if (StatusCodeData == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  //

+  // Fill in the extended data header

+  //

+  StatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA);

+  StatusCodeData->Size = (UINT16)ExtendedDataSize;

+  if (ExtendedDataGuid == NULL) {

+    ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid;

+  }

+  CopyGuid (&StatusCodeData->Type, ExtendedDataGuid);

+

+  //

+  // Fill in the extended data buffer

+  //

+  CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize);

+

+  //

+  // Report the status code

+  //

+  if (CallerId == NULL) {

+    CallerId = &gEfiCallerIdGuid;

+  }

+  Status = InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData);

+

+  //

+  // Free the allocated buffer

+  //

+  gBS->FreePool (StatusCodeData);

+

+  return Status;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLib.c b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLib.c
new file mode 100644
index 0000000..064a17b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLib.c
@@ -0,0 +1,535 @@
+/** @file

+  Report Status Code Library for DXE Phase.

+

+  Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "ReportStatusCodeLibInternal.h"

+ 

+/**

+  Internal worker function that reports a status code through the Status Code Protocol

+

+  This function checks to see if a Status Code Protocol is present in the handle

+  database.  If a Status Code Protocol is not present, then EFI_UNSUPPORTED is

+  returned.  If a Status Code Protocol is present, then it is cached in gStatusCode,

+  and the ReportStatusCode() service of the Status Code Protocol is called passing in

+  Type, Value, Instance, CallerId, and Data.  The result of this call is returned.

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  Instance          Status code instance number.

+  @param  CallerId          Pointer to a GUID that identifies the caller of this

+                            function.  This is an optional parameter that may be

+                            NULL.

+  @param  Data              Pointer to the extended data buffer.  This is an

+                            optional parameter that may be NULL.

+

+  @retval  EFI_SUCCESS           The status code was reported.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to report the status code.

+  @retval  EFI_UNSUPPORTED       Status Code Protocol is not available.

+

+**/

+EFI_STATUS

+InternalReportStatusCode (

+  IN EFI_STATUS_CODE_TYPE     Type,

+  IN EFI_STATUS_CODE_VALUE    Value,

+  IN UINT32                   Instance,

+  IN CONST EFI_GUID           *CallerId OPTIONAL,

+  IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL

+  )

+{

+  //

+  // A Status Code Protocol is present in the handle database, so pass in all the

+  // parameters to the ReportStatusCode() service of the Status Code Protocol

+  //

+  return (*mStatusProtocol.ReportStatusCode) (Type, Value, Instance, (EFI_GUID *) CallerId, Data);

+}

+

+

+/**

+  Computes and returns the size, in bytes, of a device path.

+

+  @param  DevicePath  A pointer to a device path.

+

+  @return  The size, in bytes, of DevicePath.

+

+**/

+UINTN

+InternalReportStatusCodeDevicePathSize (

+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath

+  )

+{

+  CONST EFI_DEVICE_PATH_PROTOCOL  *Start;

+

+  //

+  // Search for the end of the device path structure

+  //

+  Start = DevicePath;

+  while (!IsDevicePathEnd (DevicePath)) {

+    DevicePath = NextDevicePathNode (DevicePath);

+  }

+

+  //

+  // Subtract the start node from the end node and add in the size of the end node

+  //

+  return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath);

+}

+

+

+/**

+  Converts a status code to an 8-bit POST code value.

+

+  Converts the status code specified by CodeType and Value to an 8-bit POST code

+  and returns the 8-bit POST code in PostCode.  If CodeType is an

+  EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode

+  are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits

+  24..26 of Value., and TRUE is returned.  Otherwise, FALSE is returned.

+

+  If PostCode is NULL, then ASSERT().

+

+  @param  CodeType  The type of status code being converted.

+  @param  Value     The status code value being converted.

+  @param  PostCode  A pointer to the 8-bit POST code value to return.

+

+  @retval  TRUE   The status code specified by CodeType and Value was converted

+                  to an 8-bit POST code and returned in  PostCode.

+  @retval  FALSE  The status code specified by CodeType and Value could not be

+                  converted to an 8-bit POST code value.

+

+**/

+BOOLEAN

+EFIAPI

+CodeTypeToPostCode (

+  IN  EFI_STATUS_CODE_TYPE   CodeType,

+  IN  EFI_STATUS_CODE_VALUE  Value,

+  OUT UINT8                  *PostCode

+  )

+{

+  //

+  // If PostCode is NULL, then ASSERT()

+  //

+  ASSERT (PostCode != NULL);

+

+  //

+  // Convert Value to an 8 bit post code

+  //

+  if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ||

+      ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE)       ) {

+    *PostCode  = (UINT8) ((((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5) |

+                          (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f));

+    return TRUE;

+  }

+  return FALSE;

+}

+

+

+/**

+  Extracts ASSERT() information from a status code structure.

+

+  Converts the status code specified by CodeType, Value, and Data to the ASSERT()

+  arguments specified by Filename, Description, and LineNumber.  If CodeType is

+  an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and

+  Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract

+  Filename, Description, and LineNumber from the optional data area of the

+  status code buffer specified by Data.  The optional data area of Data contains

+  a Null-terminated ASCII string for the FileName, followed by a Null-terminated

+  ASCII string for the Description, followed by a 32-bit LineNumber.  If the

+  ASSERT() information could be extracted from Data, then return TRUE.

+  Otherwise, FALSE is returned.

+

+  If Data is NULL, then ASSERT().

+  If Filename is NULL, then ASSERT().

+  If Description is NULL, then ASSERT().

+  If LineNumber is NULL, then ASSERT().

+

+  @param  CodeType     The type of status code being converted.

+  @param  Value        The status code value being converted.

+  @param  Data         Pointer to status code data buffer.

+  @param  Filename     Pointer to the source file name that generated the ASSERT().

+  @param  Description  Pointer to the description of the ASSERT().

+  @param  LineNumber   Pointer to source line number that generated the ASSERT().

+

+  @retval  TRUE   The status code specified by CodeType, Value, and Data was

+                  converted ASSERT() arguments specified by Filename, Description,

+                  and LineNumber.

+  @retval  FALSE  The status code specified by CodeType, Value, and Data could

+                  not be converted to ASSERT() arguments.

+

+**/

+BOOLEAN

+EFIAPI

+ReportStatusCodeExtractAssertInfo (

+  IN EFI_STATUS_CODE_TYPE        CodeType,

+  IN EFI_STATUS_CODE_VALUE       Value,

+  IN CONST EFI_STATUS_CODE_DATA  *Data,

+  OUT CHAR8                      **Filename,

+  OUT CHAR8                      **Description,

+  OUT UINT32                     *LineNumber

+  )

+{

+  EFI_DEBUG_ASSERT_DATA  *AssertData;

+

+  ASSERT (Data        != NULL);

+  ASSERT (Filename    != NULL);

+  ASSERT (Description != NULL);

+  ASSERT (LineNumber  != NULL);

+

+  if (((CodeType & EFI_STATUS_CODE_TYPE_MASK)      == EFI_ERROR_CODE) &&

+      ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK)  == EFI_ERROR_UNRECOVERED) &&

+      ((Value    & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {

+    AssertData   = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);

+    *Filename    = (CHAR8 *)(AssertData + 1);

+    *Description = *Filename + AsciiStrLen (*Filename) + 1;

+    *LineNumber  = AssertData->LineNumber;

+    return TRUE;

+  }

+  return FALSE;

+}

+

+

+/**

+  Extracts DEBUG() information from a status code structure.

+

+  Converts the status code specified by Data to the DEBUG() arguments specified

+  by ErrorLevel, Marker, and Format.  If type GUID in Data is

+  EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and

+  Format from the optional data area of the status code buffer specified by Data.

+  The optional data area of Data contains a 32-bit ErrorLevel followed by Marker

+  which is 12 UINTN parameters, followed by a Null-terminated ASCII string for

+  the Format.  If the DEBUG() information could be extracted from Data, then

+  return TRUE.  Otherwise, FALSE is returned.

+

+  If Data is NULL, then ASSERT().

+  If ErrorLevel is NULL, then ASSERT().

+  If Marker is NULL, then ASSERT().

+  If Format is NULL, then ASSERT().

+

+  @param  Data        Pointer to status code data buffer.

+  @param  ErrorLevel  Pointer to error level mask for a debug message.

+  @param  Marker      Pointer to the variable argument list associated with Format.

+  @param  Format      Pointer to a Null-terminated ASCII format string of a

+                      debug message.

+

+  @retval  TRUE   The status code specified by Data was converted DEBUG() arguments

+                  specified by ErrorLevel, Marker, and Format.

+  @retval  FALSE  The status code specified by Data could not be converted to

+                  DEBUG() arguments.

+

+**/

+BOOLEAN

+EFIAPI

+ReportStatusCodeExtractDebugInfo (

+  IN CONST EFI_STATUS_CODE_DATA  *Data,

+  OUT UINT32                     *ErrorLevel,

+  OUT BASE_LIST                  *Marker,

+  OUT CHAR8                      **Format

+  )

+{

+  EFI_DEBUG_INFO  *DebugInfo;

+

+  ASSERT (Data          != NULL);

+  ASSERT (ErrorLevel    != NULL);

+  ASSERT (Marker     != NULL);

+  ASSERT (Format     != NULL);

+

+  //

+  // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE

+  //

+  if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {

+    return FALSE;

+  }

+

+  //

+  // Retrieve the debug information from the status code record

+  //

+  DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);

+

+  *ErrorLevel = DebugInfo->ErrorLevel;

+

+  //

+  // The first 12 * UINTN bytes of the string are really an

+  // argument stack to support varargs on the Format string.

+  //

+  *Marker = (BASE_LIST) (DebugInfo + 1);

+  *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);

+

+  return TRUE;

+}

+

+

+/**

+  Reports a status code.

+

+  Reports the status code specified by the parameters Type and Value.  Status

+  code also require an instance, caller ID, and extended data.  This function

+  passed in a zero instance, NULL extended data, and a caller ID of

+  gEfiCallerIdGuid, which is the GUID for the module.

+

+  ReportStatusCode()must actively prevent recusrsion.  If ReportStatusCode()

+  is called while processing another any other Report Status Code Library function,

+  then ReportStatusCode() must return immediately.

+

+  @param  Type   Status code type.

+  @param  Value  Status code value.

+

+  @retval  EFI_SUCCESS       The status code was reported.

+  @retval  EFI_DEVICE_ERROR  There status code could not be reported due to a

+                             device error.

+  @retval  EFI_UNSUPPORTED   Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+ReportStatusCode (

+  IN EFI_STATUS_CODE_TYPE   Type,

+  IN EFI_STATUS_CODE_VALUE  Value

+  )

+{

+  return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL);

+}

+

+

+/**

+  Reports a status code with a Device Path Protocol as the extended data.

+

+  Allocates and fills in the extended data section of a status code with the

+  Device Path Protocol specified by DevicePath.  This function is responsible

+  for allocating a buffer large enough for the standard header and the device

+  path.  The standard header is filled in with a GUID of

+  gEfiStatusCodeSpecificDataGuid.  The status code is reported with a zero

+  instance and a caller ID of gEfiCallerIdGuid.

+

+  ReportStatusCodeWithDevicePath()must actively prevent recursion.  If

+  ReportStatusCodeWithDevicePath() is called while processing another any other

+  Report Status Code Library function, then ReportStatusCodeWithDevicePath()

+  must return EFI_DEVICE_ERROR immediately.

+

+  If DevicePath is NULL, then ASSERT().

+

+  @param  Type        Status code type.

+  @param  Value       Status code value.

+  @param  DevicePath  Pointer to the Device Path Protocol to be reported.

+

+  @retval  EFI_SUCCESS           The status code was reported with the extended

+                                 data specified by DevicePath.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the

+                                 extended data section.

+  @retval  EFI_UNSUPPORTED       Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+ReportStatusCodeWithDevicePath (

+  IN EFI_STATUS_CODE_TYPE            Type,

+  IN EFI_STATUS_CODE_VALUE           Value,

+  IN CONST EFI_DEVICE_PATH_PROTOCOL  *DevicePath

+  )

+{

+  ASSERT (DevicePath != NULL);

+  return ReportStatusCodeWithExtendedData (

+           Type,

+           Value,

+           (VOID *)DevicePath,

+           InternalReportStatusCodeDevicePathSize (DevicePath)

+           );

+}

+

+

+/**

+  Reports a status code with an extended data buffer.

+

+  Allocates and fills in the extended data section of a status code with the

+  extended data specified by ExtendedData and ExtendedDataSize.  ExtendedData

+  is assumed to be one of the data structures specified in Related Definitions.

+  These data structure do not have the standard header, so this function is

+  responsible for allocating a buffer large enough for the standard header and

+  the extended data passed into this function.  The standard header is filled

+  in with a GUID of  gEfiStatusCodeSpecificDataGuid.  The status code is reported

+  with a zero instance and a caller ID of gEfiCallerIdGuid.

+

+  ReportStatusCodeWithExtendedData()must actively prevent recursion.  If

+  ReportStatusCodeWithExtendedData() is called while processing another any other

+  Report Status Code Library function, then ReportStatusCodeWithExtendedData()

+  must return EFI_DEVICE_ERROR immediately.

+

+  If ExtendedData is NULL, then ASSERT().

+  If ExtendedDataSize is 0, then ASSERT().

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  ExtendedData      Pointer to the extended data buffer to be reported.

+  @param  ExtendedDataSize  The size, in bytes, of the extended data buffer to

+                            be reported.

+

+  @retval  EFI_SUCCESS           The status code was reported with the extended

+                                 data specified by ExtendedData and ExtendedDataSize.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate the

+                                 extended data section.

+  @retval  EFI_UNSUPPORTED       Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+ReportStatusCodeWithExtendedData (

+  IN EFI_STATUS_CODE_TYPE   Type,

+  IN EFI_STATUS_CODE_VALUE  Value,

+  IN CONST VOID             *ExtendedData,

+  IN UINTN                  ExtendedDataSize

+  )

+{

+  ASSERT (ExtendedData     != NULL);

+  ASSERT (ExtendedDataSize != 0);

+  return ReportStatusCodeEx (

+           Type,

+           Value,

+           0,

+           NULL,

+           NULL,

+           ExtendedData,

+           ExtendedDataSize

+           );

+}

+

+

+/**

+  Reports a status code with full parameters.

+

+  The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize

+  is 0, then an extended data buffer is not reported.  If ExtendedData is not

+  NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.

+  ExtendedData is assumed not have the standard status code header, so this function

+  is responsible for allocating a buffer large enough for the standard header and

+  the extended data passed into this function.  The standard header is filled in

+  with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a

+  GUID of gEfiStatusCodeSpecificDataGuid is used.  The status code is reported with

+  an instance specified by Instance and a caller ID specified by CallerId.  If

+  CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.

+

+  ReportStatusCodeEx()must actively prevent recursion. If

+  ReportStatusCodeEx() is called while processing another any

+  other Report Status Code Library function, then

+  ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.

+

+  If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().

+  If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  Instance          Status code instance number.

+  @param  CallerId          Pointer to a GUID that identifies the caller of this

+                            function.  If this parameter is NULL, then a caller

+                            ID of gEfiCallerIdGuid is used.

+  @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.

+                            If this parameter is NULL, then a the status code

+                            standard header is filled in with

+                            gEfiStatusCodeSpecificDataGuid.

+  @param  ExtendedData      Pointer to the extended data buffer.  This is an

+                            optional parameter that may be NULL.

+  @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.

+

+  @retval  EFI_SUCCESS           The status code was reported.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate

+                                 the extended data section if it was specified.

+  @retval  EFI_UNSUPPORTED       Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+ReportStatusCodeEx (

+  IN EFI_STATUS_CODE_TYPE   Type,

+  IN EFI_STATUS_CODE_VALUE  Value,

+  IN UINT32                 Instance,

+  IN CONST EFI_GUID         *CallerId          OPTIONAL,

+  IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,

+  IN CONST VOID             *ExtendedData      OPTIONAL,

+  IN UINTN                  ExtendedDataSize

+  )

+{

+  EFI_STATUS  Status;

+

+  Status = InternalReportStatusCodeEx (

+             Type,

+             Value,

+             Instance,

+             CallerId,

+             ExtendedDataGuid,

+             ExtendedData,

+             ExtendedDataSize

+             );

+

+  return Status;

+}

+

+

+/**

+  Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled

+

+  This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED

+  bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.

+

+  @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is set.

+  @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is clear.

+

+**/

+BOOLEAN

+EFIAPI

+ReportProgressCodeEnabled (

+  VOID

+  )

+{

+  return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0);

+}

+

+

+/**

+  Returns TRUE if status codes of type EFI_ERROR_CODE are enabled

+

+  This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED

+  bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.

+

+  @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is set.

+  @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is clear.

+

+**/

+BOOLEAN

+EFIAPI

+ReportErrorCodeEnabled (

+  VOID

+  )

+{

+  return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0);

+}

+

+

+/**

+  Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled

+

+  This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED

+  bit of PcdReportStatusCodeProperyMask is set.  Otherwise FALSE is returned.

+

+  @retval  TRUE   The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is set.

+  @retval  FALSE  The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of

+                  PcdReportStatusCodeProperyMask is clear.

+

+**/

+BOOLEAN

+EFIAPI

+ReportDebugCodeEnabled (

+  VOID

+  )

+{

+  return (BOOLEAN) ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0);

+}

diff --git a/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLibInternal.h b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLibInternal.h
new file mode 100644
index 0000000..b2c70ca
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/Library/DxeCoreReportStatusCodeLibFromHob/ReportStatusCodeLibInternal.h
@@ -0,0 +1,118 @@
+/** @file

+  Internal Header file of Report Status Code Library.

+

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

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+#ifndef __REPORT_STATUS_CODE_LIB_INTERNAL_H__

+#define __REPORT_STATUS_CODE_LIB_INTERNAL_H__

+

+#include <Library/ReportStatusCodeLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/PcdLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/HobLib.h>

+

+#include <Guid/StatusCodeDataTypeId.h>

+#include <Guid/StatusCodeDataTypeDebug.h>

+#include <Protocol/StatusCode.h>

+

+/**

+  Internal worker function that reports a status code through the Status Code Protocol

+

+  This function checks to see if a Status Code Protocol is present in the handle

+  database.  If a Status Code Protocol is not present, then EFI_UNSUPPORTED is

+  returned.  If a Status Code Protocol is present, then it is cached in gStatusCode,

+  and the ReportStatusCode() service of the Status Code Protocol is called passing in

+  Type, Value, Instance, CallerId, and Data.  The result of this call is returned.

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  Instance          Status code instance number.

+  @param  CallerId          Pointer to a GUID that identifies the caller of this

+                            function.  This is an optional parameter that may be

+                            NULL.

+  @param  Data              Pointer to the extended data buffer.  This is an

+                            optional parameter that may be NULL.

+

+  @retval  EFI_SUCCESS           The status code was reported.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to report the status code.

+  @retval  EFI_UNSUPPORTED       Status Code Protocol is not available.

+

+**/

+EFI_STATUS

+InternalReportStatusCode (

+  IN EFI_STATUS_CODE_TYPE     Type,

+  IN EFI_STATUS_CODE_VALUE    Value,

+  IN UINT32                   Instance,

+  IN CONST EFI_GUID           *CallerId OPTIONAL,

+  IN EFI_STATUS_CODE_DATA     *Data     OPTIONAL

+  );

+

+/**

+  Reports a status code with full parameters.

+

+  The function reports a status code.  If ExtendedData is NULL and ExtendedDataSize

+  is 0, then an extended data buffer is not reported.  If ExtendedData is not

+  NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated.

+  ExtendedData is assumed not have the standard status code header, so this function

+  is responsible for allocating a buffer large enough for the standard header and

+  the extended data passed into this function.  The standard header is filled in

+  with a GUID specified by ExtendedDataGuid.  If ExtendedDataGuid is NULL, then a

+  GUID of gEfiStatusCodeSpecificDatauid is used.  The status code is reported with

+  an instance specified by Instance and a caller ID specified by CallerId.  If

+  CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used.

+

+  ReportStatusCodeEx()must actively prevent recursion.  If ReportStatusCodeEx()

+  is called while processing another any other Report Status Code Library function,

+  then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately.

+

+  If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT().

+  If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT().

+

+  @param  Type              Status code type.

+  @param  Value             Status code value.

+  @param  Instance          Status code instance number.

+  @param  CallerId          Pointer to a GUID that identifies the caller of this

+                            function.  If this parameter is NULL, then a caller

+                            ID of gEfiCallerIdGuid is used.

+  @param  ExtendedDataGuid  Pointer to the GUID for the extended data buffer.

+                            If this parameter is NULL, then a the status code

+                            standard header is filled in with

+                            gEfiStatusCodeSpecificDataGuid.

+  @param  ExtendedData      Pointer to the extended data buffer.  This is an

+                            optional parameter that may be NULL.

+  @param  ExtendedDataSize  The size, in bytes, of the extended data buffer.

+

+  @retval  EFI_SUCCESS           The status code was reported.

+  @retval  EFI_OUT_OF_RESOURCES  There were not enough resources to allocate

+                                 the extended data section if it was specified.

+  @retval  EFI_UNSUPPORTED       Report status code is not supported

+

+**/

+EFI_STATUS

+EFIAPI

+InternalReportStatusCodeEx (

+  IN EFI_STATUS_CODE_TYPE   Type,

+  IN EFI_STATUS_CODE_VALUE  Value,

+  IN UINT32                 Instance,

+  IN CONST EFI_GUID         *CallerId          OPTIONAL,

+  IN CONST EFI_GUID         *ExtendedDataGuid  OPTIONAL,

+  IN CONST VOID             *ExtendedData      OPTIONAL,

+  IN UINTN                  ExtendedDataSize

+  );

+

+extern EFI_STATUS_CODE_PROTOCOL mStatusProtocol;

+

+#endif // __REPORT_STATUS_CODE_LIB_INTERNAL__H

+

diff --git a/uefi/linaro-edk2/DuetPkg/License.txt b/uefi/linaro-edk2/DuetPkg/License.txt
new file mode 100644
index 0000000..be68999
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/License.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2012, Intel Corporation. All rights reserved.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS

+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE

+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,

+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;

+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER

+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT

+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN

+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

+POSSIBILITY OF SUCH DAMAGE.

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/ComponentName.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/ComponentName.c
new file mode 100644
index 0000000..dc4280e
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/ComponentName.c
@@ -0,0 +1,161 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  ComponentName.c

+

+Abstract:

+

+--*/

+

+#include "PciBus.h"

+

+//

+// EFI Component Name Functions

+//

+EFI_STATUS

+EFIAPI

+PciBusComponentNameGetDriverName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **DriverName

+  );

+

+EFI_STATUS

+EFIAPI

+PciBusComponentNameGetControllerName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  EFI_HANDLE                   ControllerHandle,

+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **ControllerName

+  );

+

+//

+// EFI Component Name Protocol

+//

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {

+  PciBusComponentNameGetDriverName,

+  PciBusComponentNameGetControllerName,

+  "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gPciBusComponentName2 = {

+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PciBusComponentNameGetDriverName,

+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PciBusComponentNameGetControllerName,

+  "en"

+};

+

+

+EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {

+  { "eng;en", L"PCI Bus Driver" },

+  { NULL, NULL }

+};

+

+EFI_STATUS

+EFIAPI

+PciBusComponentNameGetDriverName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **DriverName

+  )

+/*++

+

+  Routine Description:

+    Retrieves a Unicode string that is the user readable name of the EFI Driver.

+

+  Arguments:

+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+    Language   - A pointer to a three character ISO 639-2 language identifier.

+                 This is the language of the driver name that that the caller 

+                 is requesting, and it must match one of the languages specified

+                 in SupportedLanguages.  The number of languages supported by a 

+                 driver is up to the driver writer.

+    DriverName - A pointer to the Unicode string to return.  This Unicode string

+                 is the name of the driver specified by This in the language 

+                 specified by Language.

+

+  Returns:

+    EFI_SUCCESS           - The Unicode string for the Driver specified by This

+                            and the language specified by Language was returned 

+                            in DriverName.

+    EFI_INVALID_PARAMETER - Language is NULL.

+    EFI_INVALID_PARAMETER - DriverName is NULL.

+    EFI_UNSUPPORTED       - The driver specified by This does not support the 

+                            language specified by Language.

+

+--*/

+{

+  return LookupUnicodeString2 (

+           Language,

+           This->SupportedLanguages,

+           mPciBusDriverNameTable, 

+           DriverName,

+           (BOOLEAN)(This == &gPciBusComponentName)

+           );

+}

+

+EFI_STATUS

+EFIAPI

+PciBusComponentNameGetControllerName (

+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,

+  IN  EFI_HANDLE                   ControllerHandle,

+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,

+  IN  CHAR8                        *Language,

+  OUT CHAR16                       **ControllerName

+  )

+/*++

+

+  Routine Description:

+    Retrieves a Unicode string that is the user readable name of the controller

+    that is being managed by an EFI Driver.

+

+  Arguments:

+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+    ControllerHandle - The handle of a controller that the driver specified by 

+                       This is managing.  This handle specifies the controller 

+                       whose name is to be returned.

+    ChildHandle      - The handle of the child controller to retrieve the name 

+                       of.  This is an optional parameter that may be NULL.  It 

+                       will be NULL for device drivers.  It will also be NULL 

+                       for a bus drivers that wish to retrieve the name of the 

+                       bus controller.  It will not be NULL for a bus driver 

+                       that wishes to retrieve the name of a child controller.

+    Language         - A pointer to a three character ISO 639-2 language 

+                       identifier.  This is the language of the controller name 

+                       that that the caller is requesting, and it must match one

+                       of the languages specified in SupportedLanguages.  The 

+                       number of languages supported by a driver is up to the 

+                       driver writer.

+    ControllerName   - A pointer to the Unicode string to return.  This Unicode

+                       string is the name of the controller specified by 

+                       ControllerHandle and ChildHandle in the language specified

+                       by Language from the point of view of the driver specified

+                       by This. 

+

+  Returns:

+    EFI_SUCCESS           - The Unicode string for the user readable name in the 

+                            language specified by Language for the driver 

+                            specified by This was returned in DriverName.

+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.

+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.

+    EFI_INVALID_PARAMETER - Language is NULL.

+    EFI_INVALID_PARAMETER - ControllerName is NULL.

+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing 

+                            the controller specified by ControllerHandle and 

+                            ChildHandle.

+    EFI_UNSUPPORTED       - The driver specified by This does not support the 

+                            language specified by Language.

+

+--*/

+{

+  return EFI_UNSUPPORTED;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.c
new file mode 100644
index 0000000..b80869c
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.c
@@ -0,0 +1,346 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciBus.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+ 

+--*/

+

+#include "PciBus.h"

+

+//

+// PCI Bus Support Function Prototypes

+//

+

+EFI_STATUS

+EFIAPI

+PciBusEntryPoint (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  );

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  );

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  );

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,

+  IN  EFI_HANDLE                    Controller,

+  IN  UINTN                         NumberOfChildren,

+  IN  EFI_HANDLE                    *ChildHandleBuffer

+  );

+

+

+//

+// PCI Bus Driver Global Variables

+//

+

+EFI_DRIVER_BINDING_PROTOCOL                   gPciBusDriverBinding = {

+  PciBusDriverBindingSupported,

+  PciBusDriverBindingStart,

+  PciBusDriverBindingStop,

+  0xa,

+  NULL,

+  NULL

+};

+

+BOOLEAN gFullEnumeration;

+

+UINT64 gAllOne    = 0xFFFFFFFFFFFFFFFFULL;

+UINT64 gAllZero   = 0;

+ 

+//

+// PCI Bus Driver Support Functions

+//

+EFI_STATUS

+EFIAPI

+PciBusEntryPoint (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+/*++

+

+Routine Description:

+

+  Initialize the global variables

+  publish the driver binding protocol

+

+Arguments:

+

+  IN EFI_HANDLE     ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+

+Returns:

+

+  EFI_SUCCESS 

+  EFI_DEVICE_ERROR 

+

+--*/

+{

+  EFI_STATUS         Status;

+

+  //

+  // Initialize the EFI Driver Library

+  //

+  Status = EfiLibInstallDriverBindingComponentName2 (

+             ImageHandle,

+             SystemTable,

+             &gPciBusDriverBinding,

+             ImageHandle,

+             &gPciBusComponentName,

+             &gPciBusComponentName2

+             );

+  ASSERT_EFI_ERROR (Status);

+  

+  InitializePciDevicePool ();

+

+  gFullEnumeration = TRUE;

+  

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+/*++

+

+Routine Description:

+

+  Check to see if pci bus driver supports the given controller

+

+Arguments:

+  

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+

+Returns:

+

+  EFI_SUCCESS

+

+--*/

+{

+  EFI_STATUS                      Status;

+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

+  EFI_DEV_PATH_PTR                Node;

+

+  if (RemainingDevicePath != NULL) {

+    Node.DevPath = RemainingDevicePath;

+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||

+        Node.DevPath->SubType != HW_PCI_DP         ||

+        DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {

+      return EFI_UNSUPPORTED;

+    }

+  }

+  //

+  // Open the IO Abstraction(s) needed to perform the supported test

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID **) &ParentDevicePath,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (Status == EFI_ALREADY_STARTED) {

+    return EFI_SUCCESS;

+  }

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  gBS->CloseProtocol (

+        Controller,

+        &gEfiDevicePathProtocolGuid,

+        This->DriverBindingHandle,

+        Controller

+        );

+

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciRootBridgeIoProtocolGuid,

+                  (VOID **) &PciRootBridgeIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (Status == EFI_ALREADY_STARTED) {

+    return EFI_SUCCESS;

+  }

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  gBS->CloseProtocol (

+         Controller,

+         &gEfiPciRootBridgeIoProtocolGuid,

+         This->DriverBindingHandle,

+         Controller

+         );

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+  )

+/*++

+

+Routine Description:

+

+  Start to management the controller passed in

+

+Arguments:

+  

+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,

+  IN EFI_HANDLE                   Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath

+

+Returns:

+ 

+

+--*/

+{

+  EFI_STATUS                          Status;

+

+  //

+  // Enumerate the entire host bridge

+  // After enumeration, a database that records all the device information will be created

+  //

+  //

+  Status = PciEnumerator (Controller);

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  //

+  // Enable PCI device specified by remaining device path. BDS or other driver can call the

+  // start more than once.

+  //

+  

+  StartPciDevices (Controller, RemainingDevicePath);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PciBusDriverBindingStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,

+  IN  EFI_HANDLE                    Controller,

+  IN  UINTN                         NumberOfChildren,

+  IN  EFI_HANDLE                    *ChildHandleBuffer

+  )

+/*++

+

+Routine Description:

+

+  Stop one or more children created at start of pci bus driver

+  if all the the children get closed, close the protocol

+

+Arguments:

+  

+  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,

+  IN  EFI_HANDLE                    Controller,

+  IN  UINTN                         NumberOfChildren,

+  IN  EFI_HANDLE                    *ChildHandleBuffer

+

+Returns:

+

+  

+--*/

+{

+  EFI_STATUS  Status;

+  UINTN       Index;

+  BOOLEAN     AllChildrenStopped;

+

+  if (NumberOfChildren == 0) {

+    //

+    // Close the bus driver

+    //

+    gBS->CloseProtocol (

+           Controller,

+           &gEfiDevicePathProtocolGuid,

+           This->DriverBindingHandle,

+           Controller

+           );

+    gBS->CloseProtocol (

+           Controller,

+           &gEfiPciRootBridgeIoProtocolGuid,

+           This->DriverBindingHandle,

+           Controller

+           );

+

+    DestroyRootBridgeByHandle (

+      Controller

+      );

+

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Stop all the children

+  //

+

+  AllChildrenStopped = TRUE;

+

+  for (Index = 0; Index < NumberOfChildren; Index++) {

+

+    //

+    // De register all the pci device

+    //

+    Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);

+

+    if (EFI_ERROR (Status)) {

+      AllChildrenStopped = FALSE;

+    }

+  }

+

+  if (!AllChildrenStopped) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.h
new file mode 100644
index 0000000..3ddb5bf
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBus.h
@@ -0,0 +1,225 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciBus.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_BUS_H

+#define _EFI_PCI_BUS_H

+

+#include <PiDxe.h>

+

+#include <Protocol/PciIo.h>

+#include <Protocol/PciRootBridgeIo.h>

+#include <Protocol/DevicePath.h>

+#include <Protocol/Decompress.h>

+#include <Protocol/UgaIo.h>

+#include <Protocol/LoadedImage.h>

+#include <Protocol/BusSpecificDriverOverride.h>

+

+#include <Guid/PciOptionRomTable.h>

+

+#include <IndustryStandard/Pci.h>

+#include <IndustryStandard/Acpi.h>

+#include <IndustryStandard/PeImage.h>

+

+#include <Library/DebugLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/BaseLib.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/ReportStatusCodeLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/PcdLib.h>

+#include <Library/PeCoffLib.h>

+

+//

+// Driver Produced Protocol Prototypes

+//

+

+#define VGABASE1  0x3B0

+#define VGALIMIT1 0x3BB

+

+#define VGABASE2  0x3C0

+#define VGALIMIT2 0x3DF

+

+#define ISABASE   0x100

+#define ISALIMIT  0x3FF

+

+typedef enum {

+  PciBarTypeUnknown = 0,

+  PciBarTypeIo16,

+  PciBarTypeIo32,

+  PciBarTypeMem32,

+  PciBarTypePMem32,

+  PciBarTypeMem64,

+  PciBarTypePMem64,

+  PciBarTypeIo,

+  PciBarTypeMem,

+  PciBarTypeMaxType

+} PCI_BAR_TYPE;

+

+typedef struct {

+  UINT64        BaseAddress;

+  UINT64        Length;

+  UINT64        Alignment;

+  PCI_BAR_TYPE  BarType;

+  BOOLEAN       Prefetchable;

+  UINT8         MemType;

+  UINT8         Offset;

+} PCI_BAR;

+

+#define PCI_IO_DEVICE_SIGNATURE   SIGNATURE_32 ('p','c','i','o')

+

+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED        0x0001 

+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED      0x0002 

+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED      0x0004 

+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED        0x0008  

+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED   0x0010  

+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED       0x0020

+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED       0x0040

+

+

+typedef struct _PCI_IO_DEVICE {

+  UINT32                                    Signature;

+  EFI_HANDLE                                Handle;

+  EFI_PCI_IO_PROTOCOL                       PciIo;

+  LIST_ENTRY                            Link;

+

+  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;

+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *PciRootBridgeIo;

+

+  //

+  // PCI configuration space header type

+  //

+  PCI_TYPE00                                Pci;

+

+  //

+  // Bus number, Device number, Function number

+  //

+  UINT8                                     BusNumber;

+  UINT8                                     DeviceNumber;

+  UINT8                                     FunctionNumber;

+

+  //

+  // BAR for this PCI Device

+  //

+  PCI_BAR                                   PciBar[PCI_MAX_BAR];

+

+  //

+  // The bridge device this pci device is subject to

+  //

+  struct _PCI_IO_DEVICE                     *Parent;

+

+  //

+  // A linked list for children Pci Device if it is bridge device

+  //

+  LIST_ENTRY                            ChildList;

+

+  //

+  // TURE if the PCI bus driver creates the handle for this PCI device

+  //

+  BOOLEAN                                   Registered;

+

+  //

+  // TRUE if the PCI bus driver successfully allocates the resource required by

+  // this PCI device

+  //

+  BOOLEAN                                   Allocated;

+

+  //

+  // The attribute this PCI device currently set

+  //

+  UINT64                                    Attributes;

+

+  //

+  // The attributes this PCI device actually supports

+  //

+  UINT64                                    Supports;

+

+  //

+  // The resource decode the bridge supports

+  //

+  UINT32                                    Decodes;

+

+  //

+  // The OptionRom Size

+  //

+  UINT64                                    RomSize;

+

+  //

+  // TRUE if there is any EFI driver in the OptionRom

+  //

+  BOOLEAN                                   BusOverride;

+

+  //

+  //  A list tracking reserved resource on a bridge device

+  //

+  LIST_ENTRY                            ReservedResourceList;

+

+  //

+  // A list tracking image handle of platform specific overriding driver

+  //

+  LIST_ENTRY                            OptionRomDriverList;

+

+  BOOLEAN                                   IsPciExp;

+

+} PCI_IO_DEVICE;

+

+

+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \

+  CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)

+

+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \

+  CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)

+

+#define PCI_IO_DEVICE_FROM_LINK(a) \

+  CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)

+

+//

+// Global Variables

+//

+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;

+extern EFI_COMPONENT_NAME2_PROTOCOL  gPciBusComponentName2;

+extern EFI_DRIVER_BINDING_PROTOCOL  gPciBusDriverBinding;

+

+extern BOOLEAN                     gFullEnumeration;

+extern UINT64                      gAllOne;

+extern UINT64                      gAllZero;

+

+#include "PciIo.h"

+#include "PciCommand.h"

+#include "PciDeviceSupport.h"

+#include "PciEnumerator.h"

+#include "PciEnumeratorSupport.h"

+#include "PciDriverOverride.h"

+#include "PciRomTable.h"

+#include "PciOptionRomSupport.h"

+#include "PciPowerManagement.h"

+

+

+#define IS_ISA_BRIDGE(_p)       IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA)  

+#define IS_INTEL_ISA_BRIDGE(_p) (IS_CLASS2 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE) && ((_p)->Hdr.VendorId == 0x8086) && ((_p)->Hdr.DeviceId == 0x7110))

+#define IS_PCI_GFX(_p)     IS_CLASS2 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_OTHER)

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
new file mode 100644
index 0000000..86deb03
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
@@ -0,0 +1,72 @@
+## @file

+# 

+# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#  Module Name:

+#

+#  Abstract:

+#

+##

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = PciBusNoEnumerationDxe

+  FILE_GUID                      = 35C0C168-2607-4e51-BB53-448E3ED1A87F

+  MODULE_TYPE                    = UEFI_DRIVER

+  VERSION_STRING                 = 1.0

+

+  ENTRY_POINT                    = PciBusEntryPoint

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[LibraryClasses]

+  DebugLib

+  BaseLib

+  UefiLib

+  UefiBootServicesTableLib

+  UefiDriverEntryPoint

+  BaseMemoryLib

+  ReportStatusCodeLib

+  DevicePathLib

+  PeCoffLib

+

+[Sources]

+  PciBus.h

+  PciIo.h

+  PciCommand.h

+  PciDeviceSupport.h

+  PciEnumerator.h

+  PciEnumeratorSupport.h

+  PciOptionRomSupport.h

+  PciRomTable.h

+  PciPowerManagement.h

+  PciPowerManagement.c

+  PciRomTable.c

+  PciDriverOverride.h

+  PciDriverOverride.c

+  PciOptionRomSupport.c

+  PciEnumerator.c

+  PciEnumeratorSupport.c

+  PciCommand.c

+  ComponentName.c

+  PciDeviceSupport.c

+  PciBus.c

+  PciIo.c

+

+[Protocols]

+  gEfiPciRootBridgeIoProtocolGuid

+  gEfiPciIoProtocolGuid

+  gEfiDevicePathProtocolGuid

+  gEfiBusSpecificDriverOverrideProtocolGuid

+  gEfiDecompressProtocolGuid

+  

+[Guids]

+  gEfiPciOptionRomTableGuid

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.c
new file mode 100644
index 0000000..203bed3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.c
@@ -0,0 +1,453 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciCommand.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+

+EFI_STATUS 

+PciReadCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  OUT UINT16       *Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  *Command = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  return PciIo->Pci.Read (

+                PciIo, 

+                EfiPciIoWidthUint16, 

+                PCI_COMMAND_OFFSET, 

+                1, 

+                Command

+                );

+}

+  

+EFI_STATUS 

+PciSetCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16                Temp;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+  

+  Temp = Command;

+  PciIo = &PciIoDevice->PciIo;

+

+  return PciIo->Pci.Write (

+              PciIo, 

+              EfiPciIoWidthUint16, 

+              PCI_COMMAND_OFFSET, 

+              1, 

+              &Temp

+              );

+  

+}

+

+

+EFI_STATUS 

+PciEnableCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16  OldCommand;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  OldCommand = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  PciIo->Pci.Read (

+          PciIo, 

+          EfiPciIoWidthUint16, 

+          PCI_COMMAND_OFFSET, 

+          1, 

+          &OldCommand

+          );

+

+  OldCommand = (UINT16) (OldCommand | Command);

+

+  return PciIo->Pci.Write (

+              PciIo, 

+              EfiPciIoWidthUint16, 

+              PCI_COMMAND_OFFSET, 

+              1, 

+              &OldCommand

+              );

+  

+}

+

+

+EFI_STATUS 

+PciDisableCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16  OldCommand;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  OldCommand = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  PciIo->Pci.Read (

+          PciIo, 

+          EfiPciIoWidthUint16, 

+          PCI_COMMAND_OFFSET, 

+          1, 

+          &OldCommand

+          );

+

+  OldCommand = (UINT16) (OldCommand & ~(Command));

+

+  return PciIo->Pci.Write (

+            PciIo, 

+            EfiPciIoWidthUint16, 

+            PCI_COMMAND_OFFSET, 

+            1, 

+            &OldCommand

+           );

+  

+}

+

+

+

+EFI_STATUS 

+PciSetBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16                Temp;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  Temp = Command;

+  PciIo = &PciIoDevice->PciIo;

+

+  return PciIo->Pci.Write (

+                PciIo, 

+                EfiPciIoWidthUint16, 

+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+                1, 

+                &Temp

+               );

+ 

+}

+

+

+EFI_STATUS 

+PciEnableBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16  OldCommand;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  OldCommand = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  PciIo->Pci.Read (

+          PciIo, 

+          EfiPciIoWidthUint16, 

+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+          1, 

+          &OldCommand

+          );

+

+  OldCommand = (UINT16) (OldCommand | Command);

+

+  return PciIo->Pci.Write (

+              PciIo, 

+              EfiPciIoWidthUint16, 

+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+              1, 

+              &OldCommand

+             );

+  

+}

+

+EFI_STATUS 

+PciDisableBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16  OldCommand;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  OldCommand = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  PciIo->Pci.Read (

+          PciIo, 

+          EfiPciIoWidthUint16, 

+          PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+          1, 

+          &OldCommand

+          );

+

+  OldCommand = (UINT16) (OldCommand & ~(Command));

+

+  return PciIo->Pci.Write (

+              PciIo, 

+              EfiPciIoWidthUint16, 

+              PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+              1, 

+              &OldCommand

+              );

+ 

+}

+

+

+

+EFI_STATUS 

+PciReadBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  OUT UINT16       *Command

+)

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+

+  *Command = 0;

+  PciIo = &PciIoDevice->PciIo;

+

+  return PciIo->Pci.Read (

+                PciIo, 

+                EfiPciIoWidthUint16, 

+                PCI_BRIDGE_CONTROL_REGISTER_OFFSET, 

+                1, 

+                Command

+                );

+ 

+}

+

+BOOLEAN

+PciCapabilitySupport (

+  IN PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+  

+  None

+

+--*/

+// TODO:    PciIoDevice - add argument and description to function comment

+{

+

+  if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+EFI_STATUS

+LocateCapabilityRegBlock (

+  IN     PCI_IO_DEVICE *PciIoDevice,

+  IN     UINT8         CapId,

+  IN OUT UINT8         *Offset,

+     OUT UINT8         *NextRegBlock OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  Locate Capability register.

+

+Arguments:

+

+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.

+  CapId               - The capability ID.

+  Offset              - A pointer to the offset. 

+                        As input: the default offset; 

+                        As output: the offset of the found block.

+  NextRegBlock        - An optional pointer to return the value of next block.

+

+Returns:

+  

+  EFI_UNSUPPORTED     - The Pci Io device is not supported.

+  EFI_NOT_FOUND       - The Pci Io device cannot be found.

+  EFI_SUCCESS         - The Pci Io device is successfully located.

+

+--*/

+{

+  UINT8   CapabilityPtr;

+  UINT16  CapabilityEntry;

+  UINT8   CapabilityID;

+

+  //

+  // To check the capability of this device supports

+  //

+  if (!PciCapabilitySupport (PciIoDevice)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (*Offset != 0) {

+    CapabilityPtr = *Offset;

+  } else {

+

+    CapabilityPtr = 0;

+    if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {

+

+      PciIoDevice->PciIo.Pci.Read (

+                               &PciIoDevice->PciIo,

+                               EfiPciIoWidthUint8,

+                               EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,

+                               1,

+                               &CapabilityPtr

+                               );

+    } else {

+

+      PciIoDevice->PciIo.Pci.Read (

+                               &PciIoDevice->PciIo,

+                               EfiPciIoWidthUint8,

+                               PCI_CAPBILITY_POINTER_OFFSET,

+                               1,

+                               &CapabilityPtr

+                               );

+    }

+  }

+

+  while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {

+    PciIoDevice->PciIo.Pci.Read (

+                             &PciIoDevice->PciIo,

+                             EfiPciIoWidthUint16,

+                             CapabilityPtr,

+                             1,

+                             &CapabilityEntry

+                             );

+

+    CapabilityID = (UINT8) CapabilityEntry;

+

+    if (CapabilityID == CapId) {

+      *Offset = CapabilityPtr;

+      if (NextRegBlock != NULL) {

+        *NextRegBlock = (UINT8) (CapabilityEntry >> 8);

+      }

+

+      return EFI_SUCCESS;

+    }

+

+    CapabilityPtr = (UINT8) (CapabilityEntry >> 8);

+  }

+

+  return EFI_NOT_FOUND;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.h
new file mode 100644
index 0000000..2c724df
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciCommand.h
@@ -0,0 +1,167 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  

+    PciCommand.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_COMMAND_H

+#define _EFI_PCI_COMMAND_H

+

+#include "PciBus.h"

+

+//

+// The PCI Command register bits owned by PCI Bus driver.

+//

+// They should be cleared at the beginning. The other registers

+// are owned by chipset, we should not touch them.

+//

+#define EFI_PCI_COMMAND_BITS_OWNED                          ( \

+                EFI_PCI_COMMAND_IO_SPACE                    | \

+                EFI_PCI_COMMAND_MEMORY_SPACE                | \

+                EFI_PCI_COMMAND_BUS_MASTER                  | \

+                EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE | \

+                EFI_PCI_COMMAND_VGA_PALETTE_SNOOP           | \

+                EFI_PCI_COMMAND_FAST_BACK_TO_BACK             \

+                )

+

+//

+// The PCI Bridge Control register bits owned by PCI Bus driver.

+// 

+// They should be cleared at the beginning. The other registers

+// are owned by chipset, we should not touch them.

+//

+#define EFI_PCI_BRIDGE_CONTROL_BITS_OWNED                   ( \

+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \

+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \

+                EFI_PCI_BRIDGE_CONTROL_VGA_16               | \

+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \

+                )

+

+//

+// The PCCard Bridge Control register bits owned by PCI Bus driver.

+// 

+// They should be cleared at the beginning. The other registers

+// are owned by chipset, we should not touch them.

+//

+#define EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED                ( \

+                EFI_PCI_BRIDGE_CONTROL_ISA                  | \

+                EFI_PCI_BRIDGE_CONTROL_VGA                  | \

+                EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK      \

+                )

+

+EFI_STATUS 

+PciReadCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  OUT UINT16       *Command

+);

+

+  

+EFI_STATUS 

+PciSetCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+);

+

+EFI_STATUS 

+PciEnableCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+);

+

+EFI_STATUS 

+PciDisableCommandRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+);

+

+EFI_STATUS 

+PciDisableBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+);

+

+

+EFI_STATUS 

+PciEnableBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINT16        Command

+);

+

+EFI_STATUS 

+PciReadBridgeControlRegister (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  OUT UINT16       *Command

+);

+

+BOOLEAN

+PciCapabilitySupport (

+  IN PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+LocateCapabilityRegBlock (

+  IN     PCI_IO_DEVICE *PciIoDevice,

+  IN     UINT8         CapId,

+  IN OUT UINT8         *Offset,

+     OUT UINT8         *NextRegBlock OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  Locate Capability register.

+

+Arguments:

+

+  PciIoDevice         - A pointer to the PCI_IO_DEVICE.

+  CapId               - The capability ID.

+  Offset              - A pointer to the offset. 

+                        As input: the default offset; 

+                        As output: the offset of the found block.

+  NextRegBlock        - An optional pointer to return the value of next block.

+

+Returns:

+  

+  EFI_UNSUPPORTED     - The Pci Io device is not supported.

+  EFI_NOT_FOUND       - The Pci Io device cannot be found.

+  EFI_SUCCESS         - The Pci Io device is successfully located.

+

+--*/

+;

+

+

+#endif

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c
new file mode 100644
index 0000000..bae266d
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.c
@@ -0,0 +1,973 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciDeviceSupport.c

+  

+Abstract:

+

+  This file provides routine to support Pci device node manipulation

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+//

+// This device structure is serviced as a header.

+// Its Next field points to the first root bridge device node

+//

+LIST_ENTRY  gPciDevicePool;

+

+EFI_STATUS

+InitializePciDevicePool (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  Initialize the gPciDevicePool

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  InitializeListHead (&gPciDevicePool);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+InsertRootBridge (

+  IN PCI_IO_DEVICE *RootBridge

+  )

+/*++

+

+Routine Description:

+

+  Insert a root bridge into PCI device pool

+

+Arguments:

+

+  RootBridge    - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+{

+  InsertTailList (&gPciDevicePool, &(RootBridge->Link));

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+InsertPciDevice (

+  PCI_IO_DEVICE *Bridge,

+  PCI_IO_DEVICE *PciDeviceNode

+  )

+/*++

+

+Routine Description:

+

+  This function is used to insert a PCI device node under

+  a bridge

+

+Arguments:

+  Bridge        - A pointer to the PCI_IO_DEVICE.

+  PciDeviceNode - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+

+{

+

+  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));

+  PciDeviceNode->Parent = Bridge;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+DestroyRootBridge (

+  IN PCI_IO_DEVICE *RootBridge

+  )

+/*++

+

+Routine Description:

+

+  

+Arguments:

+

+  RootBridge   - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+{

+  DestroyPciDeviceTree (RootBridge);

+

+  gBS->FreePool (RootBridge);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+DestroyPciDeviceTree (

+  IN PCI_IO_DEVICE *Bridge

+  )

+/*++

+

+Routine Description:

+

+  Destroy all the pci device node under the bridge.

+  Bridge itself is not included.

+

+Arguments:

+

+  Bridge   - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+{

+  LIST_ENTRY  *CurrentLink;

+  PCI_IO_DEVICE   *Temp;

+

+  while (!IsListEmpty (&Bridge->ChildList)) {

+

+    CurrentLink = Bridge->ChildList.ForwardLink;

+

+    //

+    // Remove this node from the linked list

+    //

+    RemoveEntryList (CurrentLink);

+

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+

+    if (IS_PCI_BRIDGE (&(Temp->Pci))) {

+      DestroyPciDeviceTree (Temp);

+    }

+    gBS->FreePool (Temp);

+  }

+  

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+DestroyRootBridgeByHandle (

+  EFI_HANDLE Controller

+  )

+/*++

+

+Routine Description:

+

+  Destroy all device nodes under the root bridge

+  specified by Controller. 

+  The root bridge itself is also included.

+

+Arguments:

+

+  Controller   - An efi handle.

+

+Returns:

+

+  None

+

+--*/

+{

+

+  LIST_ENTRY  *CurrentLink;

+  PCI_IO_DEVICE   *Temp;

+

+  CurrentLink = gPciDevicePool.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &gPciDevicePool) {

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+

+    if (Temp->Handle == Controller) {

+

+      RemoveEntryList (CurrentLink);

+

+      DestroyPciDeviceTree (Temp);

+

+      gBS->FreePool(Temp);

+

+      return EFI_SUCCESS;

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+EFI_STATUS

+RegisterPciDevice (

+  IN  EFI_HANDLE                     Controller,

+  IN  PCI_IO_DEVICE                  *PciIoDevice,

+  OUT EFI_HANDLE                     *Handle OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  This function registers the PCI IO device. It creates a handle for this PCI IO device 

+  (if the handle does not exist), attaches appropriate protocols onto the handle, does

+  necessary initialization, and sets up parent/child relationship with its bus controller.

+

+Arguments:

+

+  Controller    - An EFI handle for the PCI bus controller.

+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.

+  Handle        - A pointer to hold the EFI handle for the PCI IO device.

+

+Returns:

+

+  EFI_SUCCESS   - The PCI device is successfully registered.

+  Others        - An error occurred when registering the PCI device.

+

+--*/

+{

+  EFI_STATUS          Status;

+  UINT8               PciExpressCapRegOffset;

+

+  //

+  // Install the pciio protocol, device path protocol and 

+  // Bus Specific Driver Override Protocol

+  //

+

+  if (PciIoDevice->BusOverride) {

+    Status = gBS->InstallMultipleProtocolInterfaces (

+                  &PciIoDevice->Handle,             

+                  &gEfiDevicePathProtocolGuid,

+                  PciIoDevice->DevicePath,

+                  &gEfiPciIoProtocolGuid,

+                  &PciIoDevice->PciIo,

+                  &gEfiBusSpecificDriverOverrideProtocolGuid,

+                  &PciIoDevice->PciDriverOverride,

+                  NULL

+                  );

+  } else {

+    Status = gBS->InstallMultipleProtocolInterfaces (

+                  &PciIoDevice->Handle,             

+                  &gEfiDevicePathProtocolGuid,

+                  PciIoDevice->DevicePath,

+                  &gEfiPciIoProtocolGuid,

+                  &PciIoDevice->PciIo,

+                  NULL

+                  );

+  }

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  } else {

+    Status = gBS->OpenProtocol (

+                    Controller,           

+                    &gEfiPciRootBridgeIoProtocolGuid, 

+                    (VOID **)&(PciIoDevice->PciRootBridgeIo),

+                    gPciBusDriverBinding.DriverBindingHandle,

+                    PciIoDevice->Handle,   

+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+                    );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+  }

+

+  if (Handle != NULL) {

+    *Handle = PciIoDevice->Handle;

+  }

+

+  //

+  // Detect if PCI Express Device

+  //

+  PciExpressCapRegOffset = 0;

+  Status = LocateCapabilityRegBlock (

+             PciIoDevice,

+             EFI_PCI_CAPABILITY_ID_PCIEXP,

+             &PciExpressCapRegOffset,

+             NULL

+             );

+  if (!EFI_ERROR (Status)) {

+    PciIoDevice->IsPciExp = TRUE;

+    DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber));

+  }

+  

+  //

+  // Indicate the pci device is registered

+  //

+  PciIoDevice->Registered = TRUE;

+

+  return EFI_SUCCESS;

+}

+

+

+EFI_STATUS

+DeRegisterPciDevice (

+  IN  EFI_HANDLE                     Controller,

+  IN  EFI_HANDLE                     Handle

+  )

+/*++

+

+Routine Description:

+

+  This function is used to de-register the PCI device from the EFI,

+  That includes un-installing PciIo protocol from the specified PCI 

+  device handle.

+

+Arguments:

+

+  Controller   - An efi handle.

+  Handle       - An efi handle.

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_PCI_IO_PROTOCOL             *PciIo;

+  EFI_STATUS                      Status;

+  PCI_IO_DEVICE                   *PciIoDevice;

+  PCI_IO_DEVICE                   *Node;

+  LIST_ENTRY                  *CurrentLink;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

+

+  Status = gBS->OpenProtocol (

+                  Handle,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  gPciBusDriverBinding.DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                  );

+  if (!EFI_ERROR (Status)) {

+    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);

+

+    //

+    // If it is already de-registered

+    //

+    if (!PciIoDevice->Registered) {

+      return EFI_SUCCESS;

+    }

+

+    //

+    // If it is PPB, first de-register its children

+    //

+

+    if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) {

+

+      CurrentLink = PciIoDevice->ChildList.ForwardLink;

+

+      while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {

+        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+        Status  = DeRegisterPciDevice (Controller, Node->Handle);

+

+        if (EFI_ERROR (Status)) {

+          return Status;

+        }

+

+        CurrentLink = CurrentLink->ForwardLink;

+      }

+    }

+

+    //

+    // First disconnect this device

+    //

+//    PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo),

+//                                    EfiPciIoAttributeOperationDisable,

+//                                    EFI_PCI_DEVICE_ENABLE,

+//                                    NULL

+//                                    );

+       

+    //

+    // Close the child handle

+    //

+    Status = gBS->CloseProtocol (

+                    Controller,

+                    &gEfiPciRootBridgeIoProtocolGuid,

+                    gPciBusDriverBinding.DriverBindingHandle,

+                    Handle

+                    );

+

+    //

+    // Un-install the device path protocol and pci io protocol

+    //

+    if (PciIoDevice->BusOverride) {

+      Status = gBS->UninstallMultipleProtocolInterfaces (

+                      Handle,

+                      &gEfiDevicePathProtocolGuid,

+                      PciIoDevice->DevicePath,

+                      &gEfiPciIoProtocolGuid,

+                      &PciIoDevice->PciIo,

+                      &gEfiBusSpecificDriverOverrideProtocolGuid,

+                      &PciIoDevice->PciDriverOverride,

+                      NULL

+                      );

+    } else {

+      Status = gBS->UninstallMultipleProtocolInterfaces (

+                      Handle,

+                      &gEfiDevicePathProtocolGuid,

+                      PciIoDevice->DevicePath,

+                      &gEfiPciIoProtocolGuid,

+                      &PciIoDevice->PciIo,

+                      NULL

+                      );

+    }

+

+    if (EFI_ERROR (Status)) {

+      gBS->OpenProtocol (

+            Controller,

+            &gEfiPciRootBridgeIoProtocolGuid,

+            (VOID **) &PciRootBridgeIo,

+            gPciBusDriverBinding.DriverBindingHandle,

+            Handle,

+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+            );

+      return Status;

+    }

+    

+    //

+    // The Device Driver should disable this device after disconnect

+    // so the Pci Bus driver will not touch this device any more.

+    // Restore the register field to the original value

+    //

+    PciIoDevice->Registered = FALSE;

+    PciIoDevice->Handle     = NULL;

+  } else {

+

+    //

+    // Handle may be closed before

+    //

+    return EFI_SUCCESS;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EnableBridgeAttributes (

+  IN PCI_IO_DEVICE                       *PciIoDevice

+  )

+{

+  PCI_TYPE01                PciData;

+

+  //

+  // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge

+  //       directly, because some legacy BIOS will NOT assign

+  //       IO or Memory resource for a bridge who has no child

+  //       device. So we add check IO or Memory here.

+  //

+

+  PciIoDevice->PciIo.Pci.Read (

+                           &PciIoDevice->PciIo,

+                           EfiPciIoWidthUint8,

+                           0,

+                           sizeof (PciData),

+                           &PciData

+                           );

+

+  if ((((PciData.Bridge.IoBase & 0xF) == 0) &&

+        (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||

+      (((PciData.Bridge.IoBase & 0xF) == 1) &&

+        ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {

+    PciIoDevice->PciIo.Attributes(

+                         &(PciIoDevice->PciIo),

+                         EfiPciIoAttributeOperationEnable,

+                         (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),

+                         NULL

+                         );

+  }

+  if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {

+    PciIoDevice->PciIo.Attributes(

+                         &(PciIoDevice->PciIo),

+                         EfiPciIoAttributeOperationEnable,

+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),

+                         NULL

+                         );

+  }

+  if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&

+        (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||

+      (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&

+        ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {

+    PciIoDevice->PciIo.Attributes(

+                         &(PciIoDevice->PciIo),

+                         EfiPciIoAttributeOperationEnable,

+                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),

+                         NULL

+                         );

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS 

+StartPciDevicesOnBridge (

+  IN EFI_HANDLE                          Controller,

+  IN PCI_IO_DEVICE                       *RootBridge,

+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath 

+  )

+/*++

+

+Routine Description:

+

+  Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge

+

+Arguments:

+

+  Controller          - An efi handle.

+  RootBridge          - A pointer to the PCI_IO_DEVICE.

+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.

+  NumberOfChildren    - Children number.

+  ChildHandleBuffer   - A pointer to the child handle buffer.

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE             *Temp;

+  PCI_IO_DEVICE             *PciIoDevice;

+  EFI_DEV_PATH_PTR          Node;

+  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;

+  EFI_STATUS                Status;

+  LIST_ENTRY            *CurrentLink;

+

+  CurrentLink = RootBridge->ChildList.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {

+

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+    if (RemainingDevicePath != NULL) {

+

+      Node.DevPath = RemainingDevicePath;

+

+      if (Node.Pci->Device != Temp->DeviceNumber || 

+          Node.Pci->Function != Temp->FunctionNumber) {

+        CurrentLink = CurrentLink->ForwardLink;

+        continue;

+      }

+

+      //

+      // Check if the device has been assigned with required resource

+      //

+      if (!Temp->Allocated) {

+        return EFI_NOT_READY;

+      }

+      

+      //

+      // Check if the current node has been registered before

+      // If it is not, register it

+      //

+      if (!Temp->Registered) {

+        PciIoDevice = Temp;

+

+        Status = RegisterPciDevice (

+                  Controller,

+                  PciIoDevice,

+                  NULL

+                  );

+

+      }

+      

+      //

+      // Get the next device path

+      //

+      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);

+      if (IsDevicePathEnd (CurrentDevicePath)) {

+        return EFI_SUCCESS;

+      }

+  

+      //

+      // If it is a PPB

+      //

+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {

+        Status = StartPciDevicesOnBridge (

+                  Controller,

+                  Temp,

+                  CurrentDevicePath

+                  );

+        EnableBridgeAttributes (Temp);

+

+        return Status;

+      } else {

+

+        //

+        // Currently, the PCI bus driver only support PCI-PCI bridge

+        //

+        return EFI_UNSUPPORTED;

+      }

+

+    } else {

+

+      //

+      // If remaining device path is NULL,

+      // try to enable all the pci devices under this bridge

+      //

+

+      if (!Temp->Registered && Temp->Allocated) {

+

+        PciIoDevice = Temp;

+

+        Status = RegisterPciDevice (

+                  Controller,

+                  PciIoDevice,

+                  NULL

+                  );

+

+      }

+

+      if (IS_PCI_BRIDGE (&(Temp->Pci))) {

+        Status = StartPciDevicesOnBridge ( 

+                   Controller,

+                   Temp,

+                   RemainingDevicePath

+                   );

+        EnableBridgeAttributes (Temp);

+      }

+

+      CurrentLink = CurrentLink->ForwardLink;

+      continue;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+EFI_STATUS

+StartPciDevices (

+  IN EFI_HANDLE                         Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath

+  )

+/*++

+

+Routine Description:

+

+  Start to manage the PCI device according to RemainingDevicePath

+  If RemainingDevicePath == NULL, the PCI bus driver will start 

+  to manage all the PCI devices it found previously

+

+Arguments:

+  Controller          - An efi handle.

+  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_DEV_PATH_PTR  Node;

+  PCI_IO_DEVICE     *RootBridge;

+  LIST_ENTRY    *CurrentLink;

+

+  if (RemainingDevicePath != NULL) {

+

+    //

+    // Check if the RemainingDevicePath is valid

+    //

+    Node.DevPath = RemainingDevicePath;

+    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||

+        Node.DevPath->SubType != HW_PCI_DP         ||

+        DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)

+        ) {

+      return EFI_UNSUPPORTED;

+    }

+  }

+

+  CurrentLink = gPciDevicePool.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &gPciDevicePool) {

+

+    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+    //

+    // Locate the right root bridge to start

+    //

+    if (RootBridge->Handle == Controller) {

+      StartPciDevicesOnBridge (

+        Controller,

+        RootBridge,

+        RemainingDevicePath

+        );

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return EFI_SUCCESS;

+}

+

+PCI_IO_DEVICE *

+CreateRootBridge (

+  IN EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+

+Arguments:

+  RootBridgeHandle   - An efi handle.

+

+Returns:

+

+  None

+

+--*/

+{

+

+  EFI_STATUS                      Status;

+  PCI_IO_DEVICE                   *Dev;

+

+  Dev = NULL;

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  sizeof (PCI_IO_DEVICE),

+                  (VOID **) &Dev

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return NULL;

+  }

+

+  ZeroMem (Dev, sizeof (PCI_IO_DEVICE));

+  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;

+  Dev->Handle     = RootBridgeHandle;

+  InitializeListHead (&Dev->ChildList);

+

+  return Dev;

+}

+

+PCI_IO_DEVICE *

+GetRootBridgeByHandle (

+  EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+

+Arguments:

+

+  RootBridgeHandle    - An efi handle.

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE   *RootBridgeDev;

+  LIST_ENTRY  *CurrentLink;

+

+  CurrentLink = gPciDevicePool.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &gPciDevicePool) {

+

+    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+    if (RootBridgeDev->Handle == RootBridgeHandle) {

+      return RootBridgeDev;

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return NULL;

+}

+

+BOOLEAN

+RootBridgeExisted (

+  IN EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+  This function searches if RootBridgeHandle has already existed

+  in current device pool.

+

+  If so, it means the given root bridge has been already enumerated.

+

+Arguments:

+

+  RootBridgeHandle   - An efi handle.

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE *Bridge;

+

+  Bridge = GetRootBridgeByHandle (RootBridgeHandle);

+

+  if (Bridge != NULL) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+BOOLEAN

+PciDeviceExisted (

+  IN PCI_IO_DEVICE    *Bridge,

+  IN PCI_IO_DEVICE    *PciIoDevice

+  )

+/*++

+

+Routine Description:

+  

+Arguments:

+

+  Bridge       - A pointer to the PCI_IO_DEVICE.

+  PciIoDevice  - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+{

+

+  PCI_IO_DEVICE   *Temp;

+  LIST_ENTRY  *CurrentLink;

+

+  CurrentLink = Bridge->ChildList.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &Bridge->ChildList) {

+

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+

+    if (Temp == PciIoDevice) {

+      return TRUE;

+    }

+

+    if (!IsListEmpty (&Temp->ChildList)) {

+      if (PciDeviceExisted (Temp, PciIoDevice)) {

+        return TRUE;

+      }

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return FALSE;

+}

+

+PCI_IO_DEVICE *

+ActiveVGADeviceOnTheSameSegment (

+  IN PCI_IO_DEVICE        *VgaDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+  VgaDevice    - A pointer to the PCI_IO_DEVICE.

+  

+Returns:

+

+  None

+

+--*/

+{

+  LIST_ENTRY  *CurrentLink;

+  PCI_IO_DEVICE   *Temp;

+

+  CurrentLink = gPciDevicePool.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &gPciDevicePool) {

+

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+

+    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {

+

+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);

+

+      if (Temp != NULL) {

+        return Temp;

+      }

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return NULL;

+}

+

+PCI_IO_DEVICE *

+ActiveVGADeviceOnTheRootBridge (

+  IN PCI_IO_DEVICE        *RootBridge

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+  RootBridge    - A pointer to the PCI_IO_DEVICE.

+

+Returns:

+

+  None

+

+--*/

+{

+  LIST_ENTRY  *CurrentLink;

+  PCI_IO_DEVICE   *Temp;

+

+  CurrentLink = RootBridge->ChildList.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {

+

+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);

+

+    if (IS_PCI_VGA(&Temp->Pci) && 

+        (Temp->Attributes &

+         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |

+          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |

+          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {

+      return Temp;

+    }

+

+    if (IS_PCI_BRIDGE (&Temp->Pci)) {

+

+      Temp = ActiveVGADeviceOnTheRootBridge (Temp);

+

+      if (Temp != NULL) {

+        return Temp;

+      }

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return NULL;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h
new file mode 100644
index 0000000..7fbe4bb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDeviceSupport.h
@@ -0,0 +1,324 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciDeviceSupport.h

+  

+Abstract:

+

+  

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_DEVICE_SUPPORT_H

+#define _EFI_PCI_DEVICE_SUPPORT_H

+

+EFI_STATUS

+InitializePciDevicePool (

+  VOID

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  None

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+InsertPciDevice (

+  PCI_IO_DEVICE *Bridge,

+  PCI_IO_DEVICE *PciDeviceNode

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Bridge        - TODO: add argument description

+  PciDeviceNode - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+DestroyPciDeviceTree (

+  IN PCI_IO_DEVICE *Bridge

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Bridge  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+DestroyRootBridgeByHandle (

+  EFI_HANDLE Controller

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Controller  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+RegisterPciDevice (

+  IN  EFI_HANDLE                     Controller,

+  IN  PCI_IO_DEVICE                  *PciIoDevice,

+  OUT EFI_HANDLE                     *Handle OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+  This function registers the PCI IO device. It creates a handle for this PCI IO device 

+  (if the handle does not exist), attaches appropriate protocols onto the handle, does

+  necessary initialization, and sets up parent/child relationship with its bus controller.

+

+Arguments:

+

+  Controller    - An EFI handle for the PCI bus controller.

+  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.

+  Handle        - A pointer to hold the EFI handle for the PCI IO device.

+

+Returns:

+

+  EFI_SUCCESS   - The PCI device is successfully registered.

+  Others        - An error occurred when registering the PCI device.

+

+--*/

+;

+

+EFI_STATUS

+DeRegisterPciDevice (

+  IN  EFI_HANDLE                     Controller,

+  IN  EFI_HANDLE                     Handle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Controller  - TODO: add argument description

+  Handle      - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+StartPciDevices (

+  IN EFI_HANDLE                         Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Controller          - TODO: add argument description

+  RemainingDevicePath - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+PCI_IO_DEVICE *

+CreateRootBridge (

+  IN EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  RootBridgeHandle  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+PCI_IO_DEVICE *

+GetRootBridgeByHandle (

+  EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  RootBridgeHandle  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS 

+InsertRootBridge (

+  PCI_IO_DEVICE *RootBridge

+);

+

+EFI_STATUS 

+DestroyRootBridge ( 

+   IN PCI_IO_DEVICE *RootBridge 

+);

+

+BOOLEAN

+RootBridgeExisted (

+  IN EFI_HANDLE RootBridgeHandle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  RootBridgeHandle  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+BOOLEAN

+PciDeviceExisted (

+  IN PCI_IO_DEVICE    *Bridge,

+  IN PCI_IO_DEVICE    *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Bridge      - TODO: add argument description

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+PCI_IO_DEVICE *

+ActiveVGADeviceOnTheSameSegment (

+  IN PCI_IO_DEVICE        *VgaDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  VgaDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+PCI_IO_DEVICE *

+ActiveVGADeviceOnTheRootBridge (

+  IN PCI_IO_DEVICE        *RootBridge

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  RootBridge  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c
new file mode 100644
index 0000000..388ee94
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.c
@@ -0,0 +1,176 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciDriverOverride.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+EFI_STATUS

+EFIAPI

+GetDriver(

+  IN     EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL          *This,

+  IN OUT EFI_HANDLE                                         *DriverImageHandle

+  );

+

+

+

+EFI_STATUS

+InitializePciDriverOverrideInstance (

+  PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  Initializes a PCI Driver Override Instance

+

+Arguments:

+  

+Returns:

+

+  None

+

+--*/

+

+{

+  PciIoDevice->PciDriverOverride.GetDriver = GetDriver;

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+GetDriver (

+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,

+  IN OUT EFI_HANDLE                                         *DriverImageHandle

+  )

+/*++

+

+Routine Description:

+

+  Get a overriding driver image

+

+Arguments:

+  

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE             *PciIoDevice;

+  LIST_ENTRY            *CurrentLink;

+  PCI_DRIVER_OVERRIDE_LIST  *Node;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);

+

+  CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;

+

+  while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {

+

+    Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);

+

+    if (*DriverImageHandle == NULL) {

+

+      *DriverImageHandle = Node->DriverImageHandle;

+      return EFI_SUCCESS;

+    }

+

+    if (*DriverImageHandle == Node->DriverImageHandle) {

+

+      if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||

+          CurrentLink->ForwardLink == NULL) {

+        return EFI_NOT_FOUND;

+      }

+

+      //

+      // Get next node

+      //

+      Node                = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);

+      *DriverImageHandle  = Node->DriverImageHandle;

+      return EFI_SUCCESS;

+    }

+

+    CurrentLink = CurrentLink->ForwardLink;

+  }

+

+  return EFI_INVALID_PARAMETER;

+}

+

+EFI_STATUS

+AddDriver (

+  IN PCI_IO_DEVICE     *PciIoDevice,

+  IN EFI_HANDLE        DriverImageHandle

+  )

+/*++

+

+Routine Description:

+

+  Add a overriding driver image

+

+Arguments:

+  

+Returns:

+

+  None

+

+--*/

+

+{

+  EFI_STATUS                    Status;

+  EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;

+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;

+  PCI_DRIVER_OVERRIDE_LIST      *Node;

+

+  Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));

+  if (Node == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Node->Signature         = DRIVER_OVERRIDE_SIGNATURE;

+  Node->DriverImageHandle = DriverImageHandle;

+

+  InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));

+

+  PciIoDevice->BusOverride  = TRUE;

+

+

+  ImageContext.Handle    = LoadedImage->ImageBase;

+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;

+

+  //

+  // Get information about the image 

+  //

+  Status = PeCoffLoaderGetImageInfo (&ImageContext);

+  if (EFI_ERROR (Status)) {

+    return EFI_SUCCESS;

+  }

+

+  if (ImageContext.Machine != EFI_IMAGE_MACHINE_EBC) {

+    return EFI_SUCCESS;

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h
new file mode 100644
index 0000000..fa2d339
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciDriverOverride.h
@@ -0,0 +1,110 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciDriverOverride.h

+  

+Abstract:

+

+  

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H

+#define _EFI_PCI_DRIVER_OVERRRIDE_H

+

+#include "PciBus.h"

+

+#define DRIVER_OVERRIDE_SIGNATURE SIGNATURE_32 ('d', 'r', 'o', 'v')

+

+typedef struct {

+  UINT32          Signature;

+  LIST_ENTRY  Link;

+  EFI_HANDLE      DriverImageHandle;

+} PCI_DRIVER_OVERRIDE_LIST;

+

+

+#define DRIVER_OVERRIDE_FROM_LINK(a) \

+  CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)

+

+

+EFI_STATUS

+InitializePciDriverOverrideInstance (

+  PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+AddDriver (

+  IN PCI_IO_DEVICE     *PciIoDevice,

+  IN EFI_HANDLE        DriverImageHandle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice       - TODO: add argument description

+  DriverImageHandle - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+GetDriver (

+  IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL              *This,

+  IN OUT EFI_HANDLE                                         *DriverImageHandle

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  This              - TODO: add argument description

+  DriverImageHandle - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c
new file mode 100644
index 0000000..9f7dd47
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.c
@@ -0,0 +1,57 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciEnumerator.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+EFI_STATUS

+PciEnumerator (

+  IN EFI_HANDLE                    Controller

+  )

+/*++

+

+Routine Description:

+

+  This routine is used to enumerate entire pci bus system 

+  in a given platform

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  //

+  // This PCI bus driver depends on the legacy BIOS

+  // to do the resource allocation

+  //

+  gFullEnumeration = FALSE;

+

+  return PciEnumeratorLight (Controller) ;

+  

+}

+

+

+

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h
new file mode 100644
index 0000000..f1125df
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumerator.h
@@ -0,0 +1,47 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciEnumerator.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_ENUMERATOR_H

+#define _EFI_PCI_ENUMERATOR_H

+

+EFI_STATUS

+PciEnumerator (

+  IN EFI_HANDLE                    Controller

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Controller  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
new file mode 100644
index 0000000..fb41727
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.c
@@ -0,0 +1,1376 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciEnumeratorSupport.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+EFI_STATUS 

+InitializePPB (

+  IN PCI_IO_DEVICE *PciIoDevice 

+);

+

+EFI_STATUS 

+InitializeP2C (

+  IN PCI_IO_DEVICE *PciIoDevice 

+);

+

+PCI_IO_DEVICE* 

+CreatePciIoDevice (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+);

+

+

+PCI_IO_DEVICE*

+GatherP2CInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+);

+

+UINTN

+PciParseBar (

+  IN PCI_IO_DEVICE  *PciIoDevice,

+  IN UINTN          Offset,

+  IN UINTN          BarIndex

+);

+

+

+EFI_STATUS

+PciSearchDevice (

+  IN PCI_IO_DEVICE                      *Bridge,

+  PCI_TYPE00                            *Pci,

+  UINT8                                 Bus,

+  UINT8                                 Device,

+  UINT8                                 Func,

+  PCI_IO_DEVICE                         **PciDevice

+);

+

+

+EFI_STATUS 

+DetermineDeviceAttribute (

+  IN PCI_IO_DEVICE                      *PciIoDevice

+);

+

+EFI_STATUS 

+BarExisted (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINTN         Offset,

+  OUT UINT32       *BarLengthValue,

+  OUT UINT32       *OriginalBarValue

+  );

+

+

+

+EFI_DEVICE_PATH_PROTOCOL*

+CreatePciDevicePath(

+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,

+  IN  PCI_IO_DEVICE            *PciIoDevice 

+);

+

+PCI_IO_DEVICE* 

+GatherDeviceInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+);

+

+PCI_IO_DEVICE* 

+GatherPPBInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+);

+

+EFI_STATUS

+PciDevicePresent (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  PCI_TYPE00                          *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+  )

+/*++

+

+Routine Description:

+

+  This routine is used to check whether the pci device is present

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT64      Address;

+  EFI_STATUS  Status;

+

+  //

+  // Create PCI address map in terms of Bus, Device and Func

+  //

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

+

+  //

+  // Read the Vendor Id register

+  //

+  Status = PciRootBridgeIo->Pci.Read (

+                                  PciRootBridgeIo,

+                                  EfiPciWidthUint32,

+                                  Address,

+                                  1,

+                                  Pci

+                                  );

+

+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {

+

+    //

+    // Read the entire config header for the device

+    //

+

+    Status = PciRootBridgeIo->Pci.Read (

+                                    PciRootBridgeIo,

+                                    EfiPciWidthUint32,

+                                    Address,

+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),

+                                    Pci

+                                    );

+

+    return EFI_SUCCESS;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+EFI_STATUS

+PciPciDeviceInfoCollector (

+  IN PCI_IO_DEVICE                      *Bridge,

+  UINT8                                 StartBusNumber

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS          Status;

+  PCI_TYPE00          Pci;

+  UINT8               Device;

+  UINT8               Func;

+  UINT8               SecBus;

+  PCI_IO_DEVICE       *PciIoDevice;

+  EFI_PCI_IO_PROTOCOL *PciIo;

+

+  Status      = EFI_SUCCESS;

+  SecBus      = 0;

+  PciIoDevice = NULL;

+

+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {

+

+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {

+

+      //

+      // Check to see whether PCI device is present

+      //

+

+      Status = PciDevicePresent (

+                Bridge->PciRootBridgeIo,

+                &Pci,

+                (UINT8) StartBusNumber,

+                (UINT8) Device,

+                (UINT8) Func

+                );

+

+      if (!EFI_ERROR (Status)) {

+

+        //

+        // Collect all the information about the PCI device discovered

+        //

+        Status = PciSearchDevice (

+                  Bridge,

+                  &Pci,

+                  (UINT8) StartBusNumber,

+                  Device,

+                  Func,

+                  &PciIoDevice

+                  );

+

+        //

+        // Recursively scan PCI busses on the other side of PCI-PCI bridges

+        //

+        //

+

+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {

+

+          //

+          // If it is PPB, we need to get the secondary bus to continue the enumeration

+          //

+          PciIo   = &(PciIoDevice->PciIo);

+

+          Status  = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);

+

+          if (EFI_ERROR (Status)) {

+            return Status;

+          }

+              

+          //

+          // Deep enumerate the next level bus

+          //

+          Status = PciPciDeviceInfoCollector (

+                    PciIoDevice,

+                    (UINT8) (SecBus)

+                    );

+

+        }

+

+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {

+

+          //

+          // Skip sub functions, this is not a multi function device

+          //

+          Func = PCI_MAX_FUNC;

+        }

+      }

+

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PciSearchDevice (

+  IN  PCI_IO_DEVICE                         *Bridge,

+  IN  PCI_TYPE00                            *Pci,

+  IN  UINT8                                 Bus,

+  IN  UINT8                                 Device,

+  IN  UINT8                                 Func,

+  OUT PCI_IO_DEVICE                         **PciDevice

+  )

+/*++

+

+Routine Description:

+

+  Search required device.

+

+Arguments:

+

+  Bridge     - A pointer to the PCI_IO_DEVICE.

+  Pci        - A pointer to the PCI_TYPE00.

+  Bus        - Bus number.

+  Device     - Device number.

+  Func       - Function number.

+  PciDevice  - The Required pci device.

+

+Returns:

+

+  Status code.

+

+--*/

+{

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = NULL;

+

+  if (!IS_PCI_BRIDGE (Pci)) {

+

+    if (IS_CARDBUS_BRIDGE (Pci)) {

+      PciIoDevice = GatherP2CInfo (

+                      Bridge->PciRootBridgeIo,

+                      Pci,

+                      Bus,

+                      Device,

+                      Func

+                      );

+      if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {

+        InitializeP2C (PciIoDevice);

+      }

+    } else {

+

+      //

+      // Create private data for Pci Device

+      //

+      PciIoDevice = GatherDeviceInfo (

+                      Bridge->PciRootBridgeIo,

+                      Pci,

+                      Bus,

+                      Device,

+                      Func

+                      );

+

+    }

+

+  } else {

+

+    //

+    // Create private data for PPB

+    //

+    PciIoDevice = GatherPPBInfo (

+                    Bridge->PciRootBridgeIo,

+                    Pci,

+                    Bus,

+                    Device,

+                    Func

+                    );

+

+    //

+    // Special initialization for PPB including making the PPB quiet

+    //

+    if ((PciIoDevice != NULL) && (gFullEnumeration == TRUE)) {

+      InitializePPB (PciIoDevice);

+    }

+  }

+

+  if (!PciIoDevice) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  

+  //

+  // Create a device path for this PCI device and store it into its private data

+  //

+  CreatePciDevicePath(

+    Bridge->DevicePath,

+    PciIoDevice 

+    );

+  

+  //

+  // Detect this function has option rom

+  //

+  if (gFullEnumeration) {

+

+    if (!IS_CARDBUS_BRIDGE (Pci)) {

+

+      GetOpRomInfo (PciIoDevice);

+

+    }

+

+    ResetPowerManagementFeature (PciIoDevice);

+    

+  } 

+  else {

+    PciRomGetRomResourceFromPciOptionRomTable (

+      &gPciBusDriverBinding,

+      PciIoDevice->PciRootBridgeIo,

+      PciIoDevice

+      );

+  }

+

+ 

+  //

+  // Insert it into a global tree for future reference

+  //

+  InsertPciDevice (Bridge, PciIoDevice);

+

+  //

+  // Determine PCI device attributes

+  //

+  DetermineDeviceAttribute (PciIoDevice);

+

+  if (PciDevice != NULL) {

+    *PciDevice = PciIoDevice;

+  }

+

+  return EFI_SUCCESS;

+}

+

+PCI_IO_DEVICE *

+GatherDeviceInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINTN                           Offset;

+  UINTN                           BarIndex;

+  PCI_IO_DEVICE                   *PciIoDevice;

+

+  PciIoDevice = CreatePciIoDevice (

+                  PciRootBridgeIo,

+                  Pci,

+                  Bus,

+                  Device,

+                  Func

+                  );

+

+  if (!PciIoDevice) {

+    return NULL;

+  }

+

+  //

+  // If it is a full enumeration, disconnect the device in advance

+  //

+  if (gFullEnumeration) {

+

+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);

+

+  }

+

+  //

+  // Start to parse the bars

+  //

+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {

+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);

+  }

+

+  return PciIoDevice;

+}

+

+PCI_IO_DEVICE *

+GatherPPBInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE                   *PciIoDevice;

+  EFI_STATUS                      Status;

+  UINT8                           Value;

+  EFI_PCI_IO_PROTOCOL             *PciIo;

+  UINT8                           Temp;

+

+  PciIoDevice = CreatePciIoDevice (

+                  PciRootBridgeIo,

+                  Pci,

+                  Bus,

+                  Device,

+                  Func

+                  );

+

+  if (!PciIoDevice) {

+    return NULL;

+  }

+  

+  if (gFullEnumeration) {

+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);

+

+    //

+    // Initalize the bridge control register

+    //

+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);

+  }

+

+  PciIo = &PciIoDevice->PciIo;

+

+  //

+  // Test whether it support 32 decode or not

+  //

+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);

+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);

+

+  if (Value) {

+    if (Value & 0x01) {

+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;

+    } else {

+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;

+    }

+  }

+

+  Status = BarExisted (

+            PciIoDevice,

+            0x24,

+            NULL,

+            NULL

+            );

+

+  //

+  // test if it supports 64 memory or not

+  //

+  if (!EFI_ERROR (Status)) {

+

+    Status = BarExisted (

+              PciIoDevice,

+              0x28,

+              NULL,

+              NULL

+              );

+

+    if (!EFI_ERROR (Status)) {

+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;

+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;

+    } else {

+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;

+    }

+  }

+

+  //

+  // Memory 32 code is required for ppb

+  //

+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;

+

+  return PciIoDevice;

+}

+

+PCI_IO_DEVICE *

+GatherP2CInfo (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE         *PciIoDevice;

+  

+  PciIoDevice = CreatePciIoDevice (

+                  PciRootBridgeIo,

+                  Pci,

+                  Bus,

+                  Device,

+                  Func

+                  );

+

+  if (!PciIoDevice) {

+    return NULL;

+  }

+

+  if (gFullEnumeration) {

+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);

+

+    //

+    // Initalize the bridge control register

+    //

+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);

+

+  }

+  //

+  // P2C only has one bar that is in 0x10

+  //

+  PciParseBar(PciIoDevice, 0x10, 0);

+  

+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |

+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |

+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;

+

+  return PciIoDevice;

+}

+

+EFI_DEVICE_PATH_PROTOCOL *

+CreatePciDevicePath (

+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,

+  IN  PCI_IO_DEVICE            *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+

+  PCI_DEVICE_PATH PciNode;

+

+  //

+  // Create PCI device path

+  //

+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;

+  PciNode.Header.SubType  = HW_PCI_DP;

+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));

+

+  PciNode.Device          = PciIoDevice->DeviceNumber;

+  PciNode.Function        = PciIoDevice->FunctionNumber;

+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);

+

+  return PciIoDevice->DevicePath;

+}

+

+EFI_STATUS

+BarExisted (

+  IN PCI_IO_DEVICE *PciIoDevice,

+  IN UINTN         Offset,

+  OUT UINT32       *BarLengthValue,

+  OUT UINT32       *OriginalBarValue

+  )

+/*++

+

+Routine Description:

+

+  Check the bar is existed or not.

+

+Arguments:

+

+  PciIoDevice       - A pointer to the PCI_IO_DEVICE.

+  Offset            - The offset.

+  BarLengthValue    - The bar length value.

+  OriginalBarValue  - The original bar value.

+

+Returns:

+

+  EFI_NOT_FOUND     - The bar don't exist.

+  EFI_SUCCESS       - The bar exist.

+

+--*/

+{

+  EFI_PCI_IO_PROTOCOL *PciIo;

+  UINT32              OriginalValue;

+  UINT32              Value;

+  EFI_TPL             OldTpl;

+

+  PciIo = &PciIoDevice->PciIo;

+

+  //

+  // Preserve the original value

+  //

+

+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);

+

+  //

+  // Raise TPL to high level to disable timer interrupt while the BAR is probed

+  //

+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);

+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);

+

+  //

+  // Write back the original value

+  //

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);

+

+  //

+  // Restore TPL to its original level

+  //

+  gBS->RestoreTPL (OldTpl);

+

+  if (BarLengthValue != NULL) {

+    *BarLengthValue = Value;

+  }

+

+  if (OriginalBarValue != NULL) {

+    *OriginalBarValue = OriginalValue;

+  }

+

+  if (Value == 0) {

+    return EFI_NOT_FOUND;

+  } else {

+    return EFI_SUCCESS;

+  }

+}

+

+

+EFI_STATUS

+DetermineDeviceAttribute (

+  IN PCI_IO_DEVICE                      *PciIoDevice

+  )

+/*++

+

+Routine Description:

+ 

+  Determine the related attributes of all devices under a Root Bridge

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT16          Command;

+  UINT16          BridgeControl;

+

+  Command = 0;

+

+  PciIoDevice->Supports |= EFI_PCI_DEVICE_ENABLE;

+  PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;

+

+  if (IS_PCI_VGA (&(PciIoDevice->Pci))){

+

+    //

+    // If the device is VGA, VGA related Attributes are supported

+    //

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO ;

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY   ;

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_IO    ;

+  }

+

+  if(IS_ISA_BRIDGE(&(PciIoDevice->Pci)) || IS_INTEL_ISA_BRIDGE(&(PciIoDevice->Pci))) {

+    //

+    // If the devie is a ISA Bridge, set the two attributes

+    //

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;

+  }

+

+  if (IS_PCI_GFX (&(PciIoDevice->Pci))) {

+

+    //

+    // If the device is GFX, then only set the EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO

+    // attribute

+    //

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO    ;

+  }

+

+

+  //

+  // If the device is IDE, IDE related attributes are supported

+  //

+  if (IS_PCI_IDE (&(PciIoDevice->Pci))) {

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO  ;

+    PciIoDevice->Supports |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO  ;

+  }

+

+  PciReadCommandRegister(PciIoDevice, &Command);

+

+  

+  if (Command & EFI_PCI_COMMAND_IO_SPACE) {

+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;

+  }

+

+  if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {

+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;

+  }

+

+  if (Command & EFI_PCI_COMMAND_BUS_MASTER) {

+    PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;

+  }

+

+  if (IS_PCI_BRIDGE (&(PciIoDevice->Pci)) || 

+      IS_CARDBUS_BRIDGE (&(PciIoDevice->Pci))){

+

+    //

+    // If it is a PPB, read the Bridge Control Register to determine

+    // the relevant attributes

+    //

+    BridgeControl = 0;

+    PciReadBridgeControlRegister(PciIoDevice, &BridgeControl);

+

+    //

+    // Determine whether the ISA bit is set

+    // If ISA Enable on Bridge is set, the PPB

+    // will block forwarding 0x100-0x3ff for each 1KB in the 

+    // first 64KB I/O range.

+    //

+    if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {

+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;

+    } 

+

+    //

+    // Determine whether the VGA bit is set

+    // If it is set, the bridge is set to decode VGA memory range

+    // and palette register range

+    //

+    if (IS_PCI_VGA (&(PciIoDevice->Pci)) &&BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {

+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;

+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;

+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;

+    }

+

+    //

+    // if the palette snoop bit is set, then the brige is set to 

+    // decode palette IO write

+    //

+    if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {

+      PciIoDevice->Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;

+    }

+  } 

+

+  return EFI_SUCCESS;

+}

+

+UINTN

+PciParseBar (

+  IN PCI_IO_DEVICE  *PciIoDevice,

+  IN UINTN          Offset,

+  IN UINTN          BarIndex

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT32      Value;

+  UINT32      OriginalValue;

+  UINT32      Mask;

+  EFI_STATUS  Status;

+

+  OriginalValue = 0;

+  Value         = 0;

+

+  Status = BarExisted (

+            PciIoDevice,

+            Offset,

+            &Value,

+            &OriginalValue

+            );

+

+  if (EFI_ERROR (Status)) {

+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;

+    PciIoDevice->PciBar[BarIndex].Length      = 0;

+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;

+

+    //

+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway

+    //

+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;

+    return Offset + 4;

+  }

+

+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;

+  if (Value & 0x01) {

+    //

+    // Device I/Os

+    //

+    Mask = 0xfffffffc;

+

+    if (Value & 0xFFFF0000) {

+      //

+      // It is a IO32 bar

+      //

+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;

+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+    } else {

+      //

+      // It is a IO16 bar

+      //

+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;

+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+    }

+    //

+    // Workaround. Some platforms inplement IO bar with 0 length

+    // Need to treat it as no-bar

+    //

+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {

+      PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;

+    }

+

+    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;

+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;

+

+  } else {

+

+    Mask  = 0xfffffff0;

+

+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;

+

+    switch (Value & 0x07) {

+

+    //

+    //memory space; anywhere in 32 bit address space

+    //

+    case 0x00:

+      if (Value & 0x08) {

+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;

+      } else {

+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;

+      }

+

+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+      break;

+

+    //

+    // memory space; anywhere in 64 bit address space

+    //

+    case 0x04:

+      if (Value & 0x08) {

+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;

+      } else {

+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;

+      }

+

+      //

+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar

+      // is regarded as an extension for the first bar. As a result

+      // the sizing will be conducted on combined 64 bit value

+      // Here just store the masked first 32bit value for future size

+      // calculation

+      //

+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+      //

+      // Increment the offset to point to next DWORD

+      //

+      Offset += 4;

+

+      Status = BarExisted (

+                PciIoDevice,

+                Offset,

+                &Value,

+                &OriginalValue

+                );

+

+      if (EFI_ERROR (Status)) {

+        return Offset + 4;

+      }

+

+      //

+      // Fix the length to support some spefic 64 bit BAR

+      //

+      Value |= ((UINT32)(-1) << HighBitSet32 (Value)); 

+

+      //

+      // Calculate the size of 64bit bar

+      //

+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);

+

+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);

+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+      break;

+

+    //

+    // reserved

+    //

+    default:

+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;

+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;

+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

+

+      break;

+    }

+  }

+  

+  //

+  // Check the length again so as to keep compatible with some special bars

+  //

+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {

+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;

+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;

+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;

+  }

+  

+  //

+  // Increment number of bar

+  //

+  return Offset + 4;

+}

+

+EFI_STATUS

+InitializePPB (

+  IN PCI_IO_DEVICE *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_PCI_IO_PROTOCOL *PciIo;

+

+  PciIo = &(PciIoDevice->PciIo);

+

+  //

+  // Put all the resource apertures including IO16

+  // Io32, pMem32, pMem64 to quiescent state

+  // Resource base all ones, Resource limit all zeros

+  //

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);

+

+  //

+  // don't support use io32 as for now

+  //

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+InitializeP2C (

+  IN PCI_IO_DEVICE *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_PCI_IO_PROTOCOL *PciIo;

+

+  PciIo = &(PciIoDevice->PciIo);

+

+  //

+  // Put all the resource apertures including IO16

+  // Io32, pMem32, pMem64 to quiescent state(

+  // Resource base all ones, Resource limit all zeros

+  //

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);

+

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);

+  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);

+

+  return EFI_SUCCESS;

+}

+

+PCI_IO_DEVICE *

+CreatePciIoDevice (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  IN PCI_TYPE00                       *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = NULL;

+

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData,

+                  sizeof (PCI_IO_DEVICE),

+                  (VOID **) &PciIoDevice

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return NULL;

+  }

+

+  ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));

+

+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;

+  PciIoDevice->Handle           = NULL;

+  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;

+  PciIoDevice->DevicePath       = NULL;

+  PciIoDevice->BusNumber        = Bus;

+  PciIoDevice->DeviceNumber     = Device;

+  PciIoDevice->FunctionNumber   = Func;

+  PciIoDevice->Decodes          = 0;

+  if (gFullEnumeration) {

+    PciIoDevice->Allocated = FALSE;

+  } else {

+    PciIoDevice->Allocated = TRUE;

+  }

+

+  PciIoDevice->Attributes         = 0;

+  PciIoDevice->Supports           = 0;

+  PciIoDevice->BusOverride        = FALSE;

+  PciIoDevice->IsPciExp           = FALSE;

+

+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));

+

+  //

+  // Initialize the PCI I/O instance structure

+  //

+

+  Status  = InitializePciIoInstance (PciIoDevice);

+  Status  = InitializePciDriverOverrideInstance (PciIoDevice);

+

+  if (EFI_ERROR (Status)) {

+    gBS->FreePool (PciIoDevice);

+    return NULL;

+  }

+

+  //

+  // Initialize the reserved resource list

+  //

+  InitializeListHead (&PciIoDevice->ReservedResourceList);

+

+  //

+  // Initialize the driver list

+  //

+  InitializeListHead (&PciIoDevice->OptionRomDriverList);

+

+  //

+  // Initialize the child list

+  //

+  InitializeListHead (&PciIoDevice->ChildList);

+

+  return PciIoDevice;

+}

+

+EFI_STATUS

+PciEnumeratorLight (

+  IN EFI_HANDLE                    Controller

+  )

+/*++

+

+Routine Description:

+

+  This routine is used to enumerate entire pci bus system 

+  in a given platform

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+

+  EFI_STATUS                        Status;

+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;

+  PCI_IO_DEVICE                     *RootBridgeDev;

+  UINT16                            MinBus;

+  UINT16                            MaxBus;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;

+

+  MinBus      = 0;

+  MaxBus      = PCI_MAX_BUS;

+  Descriptors = NULL;

+

+  //

+  // If this host bridge has been already enumerated, then return successfully

+  //

+  if (RootBridgeExisted (Controller)) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Open the IO Abstraction(s) needed to perform the supported test

+  //

+  Status = gBS->OpenProtocol (

+                  Controller      ,   

+                  &gEfiDevicePathProtocolGuid,  

+                  (VOID **)&ParentDevicePath,

+                  gPciBusDriverBinding.DriverBindingHandle,     

+                  Controller,   

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

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

+    return Status;

+  }

+

+  //

+  // Open pci root bridge io protocol

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciRootBridgeIoProtocolGuid,

+                  (VOID **) &PciRootBridgeIo,

+                  gPciBusDriverBinding.DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

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

+    return Status;

+  }

+

+  //

+  // Load all EFI Drivers from all PCI Option ROMs behind the PCI Root Bridge 

+  //

+  Status = PciRomLoadEfiDriversFromOptionRomTable (&gPciBusDriverBinding, PciRootBridgeIo);

+

+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {

+

+    //

+    // Create a device node for root bridge device with a NULL host bridge controller handle

+    //

+    RootBridgeDev = CreateRootBridge (Controller);

+

+    //

+    // Record the root bridge device path

+    //

+    RootBridgeDev->DevicePath = ParentDevicePath;

+

+    //

+    // Record the root bridge io protocol

+    //

+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;

+

+    Status = PciPciDeviceInfoCollector (

+              RootBridgeDev,

+              (UINT8) MinBus

+              );

+

+    if (!EFI_ERROR (Status)) {

+

+      //

+      // If successfully, insert the node into device pool

+      //

+      InsertRootBridge (RootBridgeDev);

+    } else {

+

+      //

+      // If unsuccessly, destroy the entire node

+      //

+      DestroyRootBridge (RootBridgeDev);

+    }

+

+    Descriptors++;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PciGetBusRange (

+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,

+  OUT    UINT16                             *MinBus,

+  OUT    UINT16                             *MaxBus,

+  OUT    UINT16                             *BusRange

+  )

+/*++

+

+Routine Description:

+

+  Get the bus range.

+

+Arguments:

+

+  Descriptors     - A pointer to the address space descriptor.

+  MinBus          - The min bus.

+  MaxBus          - The max bus.

+  BusRange        - The bus range.

+  

+Returns:

+  

+  Status Code.

+

+--*/

+{

+

+  while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {

+    if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {

+      if (MinBus != NULL) {

+        *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;

+      }

+

+      if (MaxBus != NULL) {

+        *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;

+      }

+

+      if (BusRange != NULL) {

+        *BusRange = (UINT16)(*Descriptors)->AddrLen;

+      }

+      return EFI_SUCCESS;

+    }

+

+    (*Descriptors)++;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h
new file mode 100644
index 0000000..d30c75c
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciEnumeratorSupport.h
@@ -0,0 +1,108 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciEnumeratorSupport.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H

+#define _EFI_PCI_ENUMERATOR_SUPPORT_H

+

+#include "PciBus.h"

+

+EFI_STATUS

+PciPciDeviceInfoCollector (

+  IN PCI_IO_DEVICE                      *Bridge,

+  UINT8                                 StartBusNumber

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Bridge          - TODO: add argument description

+  StartBusNumber  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+PciDevicePresent(

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  PCI_TYPE00                          *Pci,

+  UINT8                               Bus,

+  UINT8                               Device,

+  UINT8                               Func

+);

+

+EFI_STATUS

+PciEnumeratorLight (

+  IN EFI_HANDLE                    Controller

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Controller  - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+PciGetBusRange (

+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,

+  OUT    UINT16                             *MinBus,

+  OUT    UINT16                             *MaxBus,

+  OUT    UINT16                             *BusRange

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  Descriptors - TODO: add argument description

+  MinBus      - TODO: add argument description

+  MaxBus      - TODO: add argument description

+  BusRange    - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.c
new file mode 100644
index 0000000..9f47373
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.c
@@ -0,0 +1,1852 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciIo.c

+  

+Abstract:

+

+  PCI I/O Abstraction Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+//

+// PCI I/O Support Function Prototypes

+//

+//

+

+BOOLEAN 

+PciDevicesOnTheSamePath (

+  IN PCI_IO_DEVICE       *PciDevice1,

+  IN PCI_IO_DEVICE       *PciDevice2

+);

+

+

+EFI_STATUS 

+UpStreamBridgesAttributes (

+  IN  PCI_IO_DEVICE                            *PciIoDevice,

+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,

+  IN  UINT64                                   Attributes

+);

+

+

+BOOLEAN 

+CheckBarType ( 

+  IN PCI_IO_DEVICE  *PciIoDevice,

+  UINT8             BarIndex,

+  PCI_BAR_TYPE      BarType

+);

+

+

+EFI_STATUS 

+SetBootVGA ( 

+  IN  PCI_IO_DEVICE                  *PciIoDevice

+);

+

+EFI_STATUS 

+DisableBootVGA ( 

+  IN  PCI_IO_DEVICE                  *PciIoDevice

+);

+

+

+EFI_STATUS

+PciIoVerifyBarAccess (

+  PCI_IO_DEVICE                 *PciIoDevice,

+  UINT8                         BarIndex,

+  PCI_BAR_TYPE                  Type,

+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN UINTN                      Count,

+  UINT64                        *Offset

+);

+

+EFI_STATUS

+PciIoVerifyConfigAccess (

+  PCI_IO_DEVICE                 *PciIoDevice,

+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN UINTN                      Count,

+  IN UINT64                     *Offset

+);

+

+EFI_STATUS

+EFIAPI

+PciIoPollMem (

+  IN  EFI_PCI_IO_PROTOCOL        *This,

+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT8                      BarIndex,

+  IN  UINT64                     Offset,

+  IN  UINT64                     Mask,

+  IN  UINT64                     Value,

+  IN  UINT64                     Delay,

+  OUT UINT64                     *Result

+);

+  

+EFI_STATUS

+EFIAPI

+PciIoPollIo (

+  IN  EFI_PCI_IO_PROTOCOL        *This,

+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT8                      BarIndex,

+  IN  UINT64                     Offset,

+  IN  UINT64                     Mask,

+  IN  UINT64                     Value,

+  IN  UINT64                     Delay,

+  OUT UINT64                     *Result

+);    

+

+EFI_STATUS

+EFIAPI

+PciIoMemRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoMemWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoIoRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoIoWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoConfigRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT32                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoConfigWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT32                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+);

+

+EFI_STATUS

+EFIAPI

+PciIoCopyMem (

+  IN     EFI_PCI_IO_PROTOCOL  *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,

+  IN     UINT8                        DestBarIndex,

+  IN     UINT64                       DestOffset,

+  IN     UINT8                        SrcBarIndex,

+  IN     UINT64                       SrcOffset,

+  IN     UINTN                        Count

+);

+

+EFI_STATUS

+EFIAPI

+PciIoMap (

+  IN     EFI_PCI_IO_PROTOCOL            *This,

+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,

+  IN     VOID                           *HostAddress,

+  IN OUT UINTN                          *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,

+  OUT    VOID                           **Mapping

+);

+

+EFI_STATUS

+EFIAPI

+PciIoUnmap (

+  IN  EFI_PCI_IO_PROTOCOL  *This,

+  IN  VOID                 *Mapping

+);

+

+EFI_STATUS

+EFIAPI

+PciIoAllocateBuffer (

+  IN  EFI_PCI_IO_PROTOCOL    *This,

+  IN  EFI_ALLOCATE_TYPE      Type,

+  IN  EFI_MEMORY_TYPE        MemoryType,

+  IN  UINTN                  Pages,

+  OUT VOID                   **HostAddress,

+  IN  UINT64                 Attributes

+);

+

+EFI_STATUS

+EFIAPI

+PciIoFreeBuffer (

+  IN  EFI_PCI_IO_PROTOCOL   *This,

+  IN  UINTN                 Pages,

+  IN  VOID                  *HostAddress

+  );

+

+EFI_STATUS

+EFIAPI

+PciIoFlush (

+  IN  EFI_PCI_IO_PROTOCOL  *This

+  );

+

+EFI_STATUS

+EFIAPI

+PciIoGetLocation (

+  IN  EFI_PCI_IO_PROTOCOL  *This,

+  OUT UINTN                *Segment,

+  OUT UINTN                *Bus,

+  OUT UINTN                *Device,

+  OUT UINTN                *Function

+  );

+

+EFI_STATUS

+EFIAPI

+PciIoAttributes (

+  IN  EFI_PCI_IO_PROTOCOL              *This,

+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,

+  IN  UINT64                                   Attributes,

+  OUT UINT64                                   *Result   OPTIONAL

+  );

+

+EFI_STATUS

+EFIAPI

+PciIoGetBarAttributes(

+  IN  EFI_PCI_IO_PROTOCOL    *This,

+  IN  UINT8                          BarIndex,

+  OUT UINT64                         *Supports,   OPTIONAL

+  OUT VOID                           **Resources  OPTIONAL

+  );

+

+EFI_STATUS

+EFIAPI

+PciIoSetBarAttributes(

+  IN     EFI_PCI_IO_PROTOCOL  *This,

+  IN     UINT64                       Attributes,

+  IN     UINT8                        BarIndex,

+  IN OUT UINT64                       *Offset,

+  IN OUT UINT64                       *Length

+  );

+

+

+//

+// Pci Io Protocol Interface

+//

+EFI_PCI_IO_PROTOCOL  PciIoInterface = {

+  PciIoPollMem,

+  PciIoPollIo,

+  {

+    PciIoMemRead,

+    PciIoMemWrite

+  },

+  {

+    PciIoIoRead,

+    PciIoIoWrite

+  },

+  {

+    PciIoConfigRead,

+    PciIoConfigWrite

+  },

+  PciIoCopyMem,

+  PciIoMap,

+  PciIoUnmap,

+  PciIoAllocateBuffer,

+  PciIoFreeBuffer,

+  PciIoFlush,

+  PciIoGetLocation,

+  PciIoAttributes,

+  PciIoGetBarAttributes,

+  PciIoSetBarAttributes,

+  0,

+  NULL

+};

+

+

+EFI_STATUS

+InitializePciIoInstance (

+  PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  Initializes a PCI I/O Instance

+

+Arguments:

+  

+Returns:

+

+  None

+

+--*/

+

+{

+  CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PciIoVerifyBarAccess (

+  PCI_IO_DEVICE                   *PciIoDevice,

+  UINT8                           BarIndex,

+  PCI_BAR_TYPE                    Type,

+  IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,

+  IN UINTN                        Count,

+  UINT64                          *Offset

+  )

+/*++

+

+Routine Description:

+

+  Verifies access to a PCI Base Address Register (BAR)

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // BarIndex 0-5 is legal

+  //

+  if (BarIndex >= PCI_MAX_BAR) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX

+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX

+  //

+  if (Width >= EfiPciIoWidthFifoUint8 && Width <= EfiPciIoWidthFifoUint64) {

+    Count = 1;

+  }

+

+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);

+

+  if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PciIoVerifyConfigAccess (

+  PCI_IO_DEVICE                 *PciIoDevice,

+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN UINTN                      Count,

+  IN UINT64                     *Offset

+  )

+/*++

+

+Routine Description:

+

+  Verifies access to a PCI Config Header

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT64  ExtendOffset;

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX

+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX

+  //

+  Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);

+

+  if (PciIoDevice->IsPciExp) {

+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {

+      return EFI_UNSUPPORTED;

+    }

+

+    ExtendOffset  = LShiftU64 (*Offset, 32);

+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);

+    *Offset       = (*Offset) | ExtendOffset;

+

+  } else {

+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {

+      return EFI_UNSUPPORTED;

+    }

+

+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoPollMem (

+  IN  EFI_PCI_IO_PROTOCOL        *This,

+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT8                      BarIndex,

+  IN  UINT64                     Offset,

+  IN  UINT64                     Mask,

+  IN  UINT64                     Value,

+  IN  UINT64                     Delay,

+  OUT UINT64                     *Result

+  )

+/*++

+

+Routine Description:

+

+  Poll PCI Memmory

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (Width > EfiPciIoWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->PollMem (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                          Offset,

+                                          Mask,

+                                          Value,

+                                          Delay,

+                                          Result

+                                          );

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoPollIo (

+  IN  EFI_PCI_IO_PROTOCOL        *This,

+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT8                      BarIndex,

+  IN  UINT64                     Offset,

+  IN  UINT64                     Mask,

+  IN  UINT64                     Value,

+  IN  UINT64                     Delay,

+  OUT UINT64                     *Result

+  )

+/*++

+

+Routine Description:

+

+  Poll PCI IO

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width > EfiPciIoWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->PollIo (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                          Offset,

+                                          Mask,

+                                          Value,

+                                          Delay,

+                                          Result

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoMemRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI Memory Read Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  if (Buffer == NULL){

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Offset,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoMemWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI Memory Write Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  if (Buffer == NULL){

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Offset,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoIoRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI I/O Read Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  if (Buffer == NULL){

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Offset,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoIoWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT8                      BarIndex,

+  IN     UINT64                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI I/O Write Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  if (Buffer == NULL){

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Offset,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoConfigRead (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT32                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI Configuration Read Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+  UINT64        Address;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  Address     = Offset;

+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Address,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoConfigWrite (

+  IN     EFI_PCI_IO_PROTOCOL        *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT32                     Offset,

+  IN     UINTN                      Count,

+  IN OUT VOID                       *Buffer

+  )

+/*++

+

+Routine Description:

+

+  Performs a PCI Configuration Write Cycle

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+  UINT64        Address;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  Address     = Offset;

+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (

+                                              PciIoDevice->PciRootBridgeIo,

+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                              Address,

+                                              Count,

+                                              Buffer

+                                              );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoCopyMem (

+  IN EFI_PCI_IO_PROTOCOL              *This,

+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,

+  IN     UINT8                        DestBarIndex,

+  IN     UINT64                       DestOffset,

+  IN     UINT8                        SrcBarIndex,

+  IN     UINT64                       SrcOffset,

+  IN     UINTN                        Count

+  )

+/*++

+

+Routine Description:

+

+  Copy PCI Memory

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Width >= EfiPciIoWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (Width == EfiPciIoWidthFifoUint8  ||

+      Width == EfiPciIoWidthFifoUint16 ||

+      Width == EfiPciIoWidthFifoUint32 ||

+      Width == EfiPciIoWidthFifoUint64 ||

+      Width == EfiPciIoWidthFillUint8  ||

+      Width == EfiPciIoWidthFillUint16 ||

+      Width == EfiPciIoWidthFillUint32 ||

+      Width == EfiPciIoWidthFillUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                          DestOffset,

+                                          SrcOffset,

+                                          Count

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoMap (

+  IN     EFI_PCI_IO_PROTOCOL            *This,

+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,

+  IN     VOID                           *HostAddress,

+  IN OUT UINTN                          *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,

+  OUT    VOID                           **Mapping

+  )

+/*++

+

+Routine Description:

+

+  Maps a memory region for DMA

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if ((UINT32)Operation >= EfiPciIoOperationMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {

+    Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->Map (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,

+                                          HostAddress,

+                                          NumberOfBytes,

+                                          DeviceAddress,

+                                          Mapping

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoUnmap (

+  IN  EFI_PCI_IO_PROTOCOL  *This,

+  IN  VOID                 *Mapping

+  )

+/*++

+

+Routine Description:

+

+  Unmaps a memory region for DMA

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  Status = PciIoDevice->PciRootBridgeIo->Unmap (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          Mapping

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoAllocateBuffer (

+  IN  EFI_PCI_IO_PROTOCOL   *This,

+  IN  EFI_ALLOCATE_TYPE     Type,

+  IN  EFI_MEMORY_TYPE       MemoryType,

+  IN  UINTN                 Pages,

+  OUT VOID                  **HostAddress,

+  IN  UINT64                Attributes

+  )

+/*++

+

+Routine Description:

+

+  Allocates a common buffer for DMA

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+

+  if (Attributes &

+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {

+    return EFI_UNSUPPORTED;

+  }

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {

+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;

+  }

+

+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          Type,

+                                          MemoryType,

+                                          Pages,

+                                          HostAddress,

+                                          Attributes

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoFreeBuffer (

+  IN  EFI_PCI_IO_PROTOCOL   *This,

+  IN  UINTN                 Pages,

+  IN  VOID                  *HostAddress

+  )

+/*++

+

+Routine Description:

+

+  Frees a common buffer 

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+  

+  if( HostAddress == NULL ){

+     return EFI_INVALID_PARAMETER;

+  } 

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (

+                                          PciIoDevice->PciRootBridgeIo,

+                                          Pages,

+                                          HostAddress

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoFlush (

+  IN  EFI_PCI_IO_PROTOCOL  *This

+  )

+/*++

+

+Routine Description:

+

+  Flushes a DMA buffer

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+

+{

+  EFI_STATUS    Status;

+  UINT32         Register;

+  PCI_IO_DEVICE  *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  //

+  // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to 

+  // flush the posted write cycles through the PCI-PCI bridges

+  //

+  if (PciIoDevice->Parent != NULL) {

+    Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);

+  }

+

+  //

+  // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset

+  //

+  Status = PciIoDevice->PciRootBridgeIo->Flush (

+                                           PciIoDevice->PciRootBridgeIo

+                                           );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoGetLocation (

+  IN  EFI_PCI_IO_PROTOCOL  *This,

+  OUT UINTN                *Segment,

+  OUT UINTN                *Bus,

+  OUT UINTN                *Device,

+  OUT UINTN                *Function

+  )

+/*++

+

+Routine Description:

+

+  Gets a PCI device's current bus number, device number, and function number.

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE *PciIoDevice;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;

+  *Bus      = PciIoDevice->BusNumber;

+  *Device   = PciIoDevice->DeviceNumber;

+  *Function = PciIoDevice->FunctionNumber;

+

+  return EFI_SUCCESS;

+}

+

+BOOLEAN

+CheckBarType (

+  IN PCI_IO_DEVICE       *PciIoDevice,

+  UINT8                  BarIndex,

+  PCI_BAR_TYPE           BarType

+  )

+/*++

+

+Routine Description:

+

+  Sets a PCI controllers attributes on a resource range

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  switch (BarType) {

+

+  case PciBarTypeMem:

+

+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&

+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&

+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&

+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {

+      return FALSE;

+    }

+

+    return TRUE;

+

+  case PciBarTypeIo:

+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&

+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){

+      return FALSE;

+    }

+

+    return TRUE;

+

+  default:

+    break;

+  }

+

+  return FALSE;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoAttributes (

+  IN EFI_PCI_IO_PROTOCOL                       * This,

+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,

+  IN  UINT64                                   Attributes,

+  OUT UINT64                                   *Result OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+

+  PCI_IO_DEVICE *PciIoDevice;

+  PCI_IO_DEVICE *Temp;

+  UINT64         NewAttributes;

+  UINT64         PciRootBridgeSupports;

+  UINT64         PciRootBridgeAttributes;

+  UINT64         NewPciRootBridgeAttributes;

+  UINT64         NewUpStreamBridgeAttributes;

+  UINT64         ModifiedPciRootBridgeAttributes;

+  UINT16         EnableCommand;

+  UINT16         DisableCommand;

+  UINT16         EnableBridge;

+  UINT16         DisableBridge;

+  UINT16         Command;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+  NewUpStreamBridgeAttributes = 0;

+

+  EnableCommand   = 0;

+  DisableCommand  = 0;

+  EnableBridge    = 0;

+  DisableBridge   = 0;

+

+  switch (Operation) {

+  case EfiPciIoAttributeOperationGet:

+    if (Result == NULL) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    *Result = PciIoDevice->Attributes;

+    return EFI_SUCCESS;

+

+  case EfiPciIoAttributeOperationSupported:

+    if (Result == NULL) {

+      return EFI_INVALID_PARAMETER;

+    }

+

+    *Result = PciIoDevice->Supports;

+    return EFI_SUCCESS;

+

+  case EfiPciIoAttributeOperationEnable:

+    if(Attributes & ~(PciIoDevice->Supports)) {

+      return EFI_UNSUPPORTED;

+    }

+    NewAttributes = PciIoDevice->Attributes | Attributes;

+    break;

+  case EfiPciIoAttributeOperationDisable:

+    if(Attributes & ~(PciIoDevice->Supports)) {

+      return EFI_UNSUPPORTED;

+    }

+    NewAttributes = PciIoDevice->Attributes & (~Attributes);

+    break;

+  case EfiPciIoAttributeOperationSet:

+    if(Attributes & ~(PciIoDevice->Supports)) {

+      return EFI_UNSUPPORTED;

+    }

+    NewAttributes = Attributes;

+    break;

+  default:

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.

+  //

+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {

+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;

+  }

+

+  //

+  // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.

+  //

+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {

+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;

+  }

+

+  //

+  // If the attributes are already set correctly, then just return EFI_SUCCESS;

+  //

+  if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and

+  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so

+  // a call to the PCI Root Bridge I/O Protocol can be made

+  //

+

+  if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {

+    NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));

+

+    //  

+    // Get the current attributes of this PCI device's PCI Root Bridge

+    //

+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (

+                                            PciIoDevice->PciRootBridgeIo,

+                                            &PciRootBridgeSupports,

+                                            &PciRootBridgeAttributes

+                                            );

+

+    //

+    // Check to see if any of the PCI Root Bridge attributes are being modified

+    //

+    ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;

+    if (ModifiedPciRootBridgeAttributes) {

+

+      //

+      // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing

+      //

+      if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {

+  //     return EFI_UNSUPPORTED;

+      }

+      //

+      // Call the PCI Root Bridge to attempt to modify the attributes

+      //

+      Status = PciIoDevice->PciRootBridgeIo->SetAttributes (

+                                             PciIoDevice->PciRootBridgeIo,

+                                             NewPciRootBridgeAttributes,

+                                             NULL,

+                                             NULL

+                                             );

+      if (EFI_ERROR (Status)) {

+      //

+      // The PCI Root Bridge could not modify the attributes, so return the error.

+      //

+        return Status;

+      }

+    }

+  }

+

+

+  if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {

+

+

+    //

+    // Check to see if an VGA related attributes are being set.

+    //

+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {

+

+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {

+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;

+      } else {

+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;

+      }

+    }

+

+    //

+    // Check to see if an VGA related attributes are being set.

+    // If ISA Enable on the PPB is set, the PPB will block the

+    // 0x100-0x3FF for each 1KB block in the first 64K I/O block

+    //

+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {

+

+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {

+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;

+      } else {

+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;

+      }

+    }

+

+    //

+    // Check to see if an VGA related attributes are being set.

+    //

+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {

+

+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {

+        EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+      } else {

+        DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+      }

+    }

+

+  } else {

+

+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {

+

+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {

+

+        //

+        //Check if there have been an active VGA device on the same segment

+        //

+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);

+

+        if (Temp && Temp != PciIoDevice) {

+          return EFI_UNSUPPORTED;

+        }

+      }

+    }

+

+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {

+      if (IS_PCI_GFX(&PciIoDevice->Pci)) {

+

+        //

+        //Get the boot VGA on the same segement

+        //

+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);

+

+        if (!Temp) {

+

+          //

+          // If there is no VGA device on the segement, set

+          // this graphics card to decode the palette range

+          //

+          DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+        } else {

+

+          //

+          // Check these two agents are on the same path

+          //

+          if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {

+

+            //

+            // Check if they are on the same bus

+            //

+            if (Temp->Parent == PciIoDevice->Parent) {

+

+              PciReadCommandRegister (Temp, &Command);

+

+              //

+              // If they are on the same bus, either one can

+              // be set to snoop, the other set to decode

+              //

+              if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {

+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+              } else {

+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+              }

+            } else {

+

+              //

+              // If they are on  the same path but on the different bus

+              // The first agent is set to snoop, the second one set to

+              // decode

+              //

+              if (Temp->BusNumber > PciIoDevice->BusNumber) {

+                PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);

+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+              } else {

+                PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);

+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+              }

+            }

+          } else {

+

+            EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;

+          }

+        }

+      }

+    }

+  }

+

+  //

+  // Check to see of the I/O enable is being modified

+  //

+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {

+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {

+      EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;

+    } else {

+      DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;

+    }

+  }

+

+  //

+  // Check to see of the Memory enable is being modified

+  //

+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {

+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {

+      EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;

+    } else {

+      DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;

+    }

+  }

+

+  //

+  // Check to see of the Bus Master enable is being modified

+  //

+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {

+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {

+      EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;

+    } else {

+      DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;

+    }

+  }

+

+  Status = EFI_SUCCESS;

+  if (EnableCommand) {

+    Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);

+  } 

+

+  if (DisableCommand) {

+    Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);

+  }

+

+  if (EFI_ERROR(Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (EnableBridge) {

+    Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);

+  }

+

+  if (DisableBridge) {

+    Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);

+  }

+   

+  if (EFI_ERROR(Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Set the upstream bridge attributes

+  //

+  if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {

+

+    //

+    // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER

+    // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED

+    // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge

+    // 

+    NewUpStreamBridgeAttributes = Attributes & \

+                                (~(EFI_PCI_IO_ATTRIBUTE_IO | \

+                                EFI_PCI_IO_ATTRIBUTE_MEMORY | \

+                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \

+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \

+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \

+                                EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));

+

+    if (NewUpStreamBridgeAttributes){

+      UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);

+    }

+  }

+  

+  PciIoDevice->Attributes = NewAttributes;

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoGetBarAttributes (

+  IN EFI_PCI_IO_PROTOCOL             * This,

+  IN  UINT8                          BarIndex,

+  OUT UINT64                         *Supports, OPTIONAL

+  OUT VOID                           **Resources OPTIONAL

+  )

+/*++

+

+Routine Description:

+

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  UINT8                             *Configuration;

+  PCI_IO_DEVICE                     *PciIoDevice;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *AddressSpace;

+  EFI_ACPI_END_TAG_DESCRIPTOR       *End;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  if (Supports == NULL && Resources == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // This driver does not support modifications to the WRITE_COMBINE or

+  // CACHED attributes for BAR ranges.

+  //

+  if (Supports != NULL) {

+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;

+  }

+

+  if (Resources != NULL) {

+    Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));

+    if (Configuration == NULL) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+

+    AddressSpace = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;

+

+    AddressSpace->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    AddressSpace->Len          = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);

+

+    AddressSpace->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;

+    AddressSpace->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;

+    AddressSpace->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;

+

+    switch (PciIoDevice->PciBar[BarIndex].BarType) {

+    case PciBarTypeIo16:

+    case PciBarTypeIo32:

+      //

+      // Io

+      //

+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;

+      break;

+

+    case PciBarTypeMem32:

+      //

+      // Mem

+      //

+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;

+      //

+      // 32 bit

+      //

+      AddressSpace->AddrSpaceGranularity = 32;

+      break;

+

+    case PciBarTypePMem32:

+      //

+      // Mem

+      //

+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;

+      //

+      // prefechable

+      //

+      AddressSpace->SpecificFlag = 0x6;

+      //

+      // 32 bit

+      //

+      AddressSpace->AddrSpaceGranularity = 32;

+      break;

+

+    case PciBarTypeMem64:

+      //

+      // Mem

+      //

+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;

+      //

+      // 64 bit

+      //

+      AddressSpace->AddrSpaceGranularity = 64;

+      break;

+

+    case PciBarTypePMem64:

+      //

+      // Mem

+      //

+      AddressSpace->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;

+      //

+      // prefechable

+      //

+      AddressSpace->SpecificFlag = 0x6;

+      //

+      // 64 bit

+      //

+      AddressSpace->AddrSpaceGranularity = 64;

+      break;

+

+    default:

+      break;

+    }

+

+    //

+    // put the checksum

+    //

+    End           = (EFI_ACPI_END_TAG_DESCRIPTOR *) (AddressSpace + 1);

+    End->Desc     = ACPI_END_TAG_DESCRIPTOR;

+    End->Checksum = 0;

+

+    *Resources    = Configuration;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PciIoSetBarAttributes (

+  IN EFI_PCI_IO_PROTOCOL              *This,

+  IN     UINT64                       Attributes,

+  IN     UINT8                        BarIndex,

+  IN OUT UINT64                       *Offset,

+  IN OUT UINT64                       *Length

+  )

+/*++

+

+Routine Description:

+

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS    Status;

+  PCI_IO_DEVICE *PciIoDevice;

+  UINT64        NonRelativeOffset;

+  UINT64        Supports;

+

+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

+

+  //

+  // Make sure Offset and Length are not NULL

+  //

+  if (Offset == NULL || Length == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {

+    return EFI_UNSUPPORTED;

+  }

+  //

+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.

+  // If Attributes is not 0, then return EFI_UNSUPPORTED.

+  //

+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;

+

+  if (Attributes != (Attributes & Supports)) {

+    return EFI_UNSUPPORTED;

+  }

+  //

+  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and

+  // Length are valid for this PCI device.

+  //

+  NonRelativeOffset = *Offset;

+  Status = PciIoVerifyBarAccess (

+            PciIoDevice,

+            BarIndex,

+            PciBarTypeMem,

+            EfiPciIoWidthUint8,

+            (UINT32) *Length,

+            &NonRelativeOffset

+            );

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+UpStreamBridgesAttributes (

+  IN  PCI_IO_DEVICE                            *PciIoDevice,

+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,

+  IN  UINT64                                   Attributes

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  PCI_IO_DEVICE       *Parent;

+  EFI_PCI_IO_PROTOCOL *PciIo;

+

+  Parent = PciIoDevice->Parent;

+

+  while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {

+

+    //

+    // Get the PciIo Protocol

+    //

+    PciIo = &Parent->PciIo;

+

+    PciIo->Attributes (PciIo, Operation, Attributes, NULL);

+

+    Parent = Parent->Parent;

+  }

+

+  return EFI_SUCCESS;

+}

+

+BOOLEAN

+PciDevicesOnTheSamePath (

+  IN PCI_IO_DEVICE        *PciDevice1,

+  IN PCI_IO_DEVICE        *PciDevice2

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+  PciDevice1  -  The pointer to the first PCI_IO_DEVICE.

+  PciDevice2  -  The pointer to the second PCI_IO_DEVICE.

+

+Returns:

+

+  TRUE   -  The two Pci devices are on the same path.

+  FALSE  -  The two Pci devices are not on the same path.

+

+--*/

+{

+

+  if (PciDevice1->Parent == PciDevice2->Parent) {

+    return TRUE;

+  }

+

+  return (BOOLEAN) ((PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1)));

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.h
new file mode 100644
index 0000000..0810ae3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciIo.h
@@ -0,0 +1,48 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciIo.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_IO_PROTOCOL_H

+#define _EFI_PCI_IO_PROTOCOL_H

+

+EFI_STATUS

+InitializePciIoInstance (

+  PCI_IO_DEVICE  *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
new file mode 100644
index 0000000..28adb2b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
@@ -0,0 +1,557 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciOptionRomSupport.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+

+EFI_STATUS

+RomDecode (

+  IN PCI_IO_DEVICE   *PciDevice,

+  IN UINT8           RomBarIndex,

+  IN UINT32          RomBar,

+  IN BOOLEAN         Enable

+);

+

+EFI_STATUS

+GetOpRomInfo (

+  IN PCI_IO_DEVICE    *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  UINT8                           RomBarIndex;

+  UINT32                          AllOnes;

+  UINT64                          Address;

+  EFI_STATUS                      Status;

+  UINT8                           Bus;

+  UINT8                           Device;

+  UINT8                           Function;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

+

+  Bus             = PciIoDevice->BusNumber;

+  Device          = PciIoDevice->DeviceNumber;

+  Function        = PciIoDevice->FunctionNumber;

+

+  PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;

+

+  //

+  // offset is 0x30 if is not ppb

+  //

+

+  //

+  // 0x30

+  //

+  RomBarIndex = PCI_EXPANSION_ROM_BASE;

+

+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {

+    //

+    // if is ppb

+    //

+

+    //

+    // 0x38

+    //

+    RomBarIndex = PCI_BRIDGE_ROMBAR;

+  }

+  //

+  // the bit0 is 0 to prevent the enabling of the Rom address decoder

+  //

+  AllOnes = 0xfffffffe;

+  Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);

+

+  Status = PciRootBridgeIo->Pci.Write (

+                                  PciRootBridgeIo,

+                                  EfiPciWidthUint32,

+                                  Address,

+                                  1,

+                                  &AllOnes

+                                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  //

+  // read back

+  //

+  Status = PciRootBridgeIo->Pci.Read (

+                                  PciRootBridgeIo,

+                                  EfiPciWidthUint32,

+                                  Address,

+                                  1,

+                                  &AllOnes

+                                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Bits [1, 10] are reserved

+  //

+  AllOnes &= 0xFFFFF800;

+  if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {

+    return EFI_NOT_FOUND;

+  }

+  

+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));

+  DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));

+

+  PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+LoadOpRomImage (

+  IN PCI_IO_DEVICE   *PciDevice,

+  IN UINT64          ReservedMemoryBase

+  )

+/*++

+

+Routine Description:

+ 

+    Load option rom image for specified PCI device

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  UINT8                     RomBarIndex;

+  UINT8                     Indicator;

+  UINT16                    OffsetPcir;

+  UINT32                    RomBarOffset;

+  UINT32                    RomBar;

+  EFI_STATUS                retStatus;

+  BOOLEAN                   FirstCheck;

+  UINT8                     *Image;

+  PCI_EXPANSION_ROM_HEADER  *RomHeader;

+  PCI_DATA_STRUCTURE        *RomPcir;

+  UINT64                    RomSize;

+  UINT64                    RomImageSize;

+  UINT32                    LegacyImageLength;

+  UINT8                     *RomInMemory;

+  UINT8                     CodeType;

+

+  RomSize       = PciDevice->RomSize;

+

+  Indicator     = 0;

+  RomImageSize  = 0;

+  RomInMemory   = NULL;

+  CodeType      = 0xFF;

+

+  //

+  // Get the RomBarIndex

+  //

+

+  //

+  // 0x30

+  //

+  RomBarIndex = PCI_EXPANSION_ROM_BASE;

+  if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {

+    //

+    // if is ppb

+    //

+

+    //

+    // 0x38

+    //

+    RomBarIndex = PCI_BRIDGE_ROMBAR;

+  }

+  //

+  // Allocate memory for Rom header and PCIR

+  //

+  RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));

+  if (RomHeader == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));

+  if (RomPcir == NULL) {

+    gBS->FreePool (RomHeader);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  RomBar = (UINT32)ReservedMemoryBase;  

+

+  //

+  // Enable RomBar

+  //

+  RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);

+

+  RomBarOffset  = RomBar;

+  retStatus     = EFI_NOT_FOUND;

+  FirstCheck    = TRUE;

+  LegacyImageLength = 0;

+

+  do {

+    PciDevice->PciRootBridgeIo->Mem.Read (

+                                      PciDevice->PciRootBridgeIo,

+                                      EfiPciWidthUint8,

+                                      RomBarOffset,

+                                      sizeof (PCI_EXPANSION_ROM_HEADER),

+                                      (UINT8 *) RomHeader

+                                      );

+

+    if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {

+      RomBarOffset = RomBarOffset + 512;

+      if (FirstCheck) {

+        break;

+      } else {

+        RomImageSize = RomImageSize + 512;

+        continue;

+      }

+    }

+

+    FirstCheck  = FALSE;

+    OffsetPcir  = RomHeader->PcirOffset;

+    //

+    // If the pointer to the PCI Data Structure is invalid, no further images can be located. 

+    // The PCI Data Structure must be DWORD aligned. 

+    //

+    if (OffsetPcir == 0 ||

+       (OffsetPcir & 3) != 0 ||

+       RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {

+      break;

+    }

+    PciDevice->PciRootBridgeIo->Mem.Read (

+                                      PciDevice->PciRootBridgeIo,

+                                      EfiPciWidthUint8,

+                                      RomBarOffset + OffsetPcir,

+                                      sizeof (PCI_DATA_STRUCTURE),

+                                      (UINT8 *) RomPcir

+                                      );

+    //

+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.

+    //

+    if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {

+      break;

+    }

+    if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {

+      break;

+    }

+    if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {

+      CodeType = PCI_CODE_TYPE_PCAT_IMAGE;

+      LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;

+    }

+    Indicator     = RomPcir->Indicator;

+    RomImageSize  = RomImageSize + RomPcir->ImageLength * 512;

+    RomBarOffset  = RomBarOffset + RomPcir->ImageLength * 512;

+  } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));

+

+  //

+  // Some Legacy Cards do not report the correct ImageLength so used the maximum

+  // of the legacy length and the PCIR Image Length

+  //

+  if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {

+    RomImageSize = MAX (RomImageSize, LegacyImageLength);

+  }

+

+  if (RomImageSize > 0) {

+    retStatus = EFI_SUCCESS;

+    Image     = AllocatePool ((UINT32) RomImageSize);

+    if (Image == NULL) {

+      RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);

+      gBS->FreePool (RomHeader);

+      gBS->FreePool (RomPcir);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    

+    //

+    // Copy Rom image into memory

+    //

+    PciDevice->PciRootBridgeIo->Mem.Read (

+                                      PciDevice->PciRootBridgeIo,

+                                      EfiPciWidthUint8,

+                                      RomBar,

+                                      (UINT32) RomImageSize,

+                                      Image

+                                      );

+    RomInMemory = Image;

+  }

+

+  RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);

+

+  PciDevice->PciIo.RomSize  = RomImageSize;

+  PciDevice->PciIo.RomImage = RomInMemory;

+

+  //

+  // Free allocated memory

+  //

+  gBS->FreePool (RomHeader);

+  gBS->FreePool (RomPcir);

+

+  return retStatus;

+}

+

+EFI_STATUS

+RomDecode (

+  IN PCI_IO_DEVICE   *PciDevice,

+  IN UINT8           RomBarIndex,

+  IN UINT32          RomBar,

+  IN BOOLEAN         Enable

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  UINT16                          CommandValue;

+  UINT32                          Value32;

+  UINT64                          Address;

+  //EFI_STATUS                      Status;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

+  

+  PciRootBridgeIo = PciDevice->PciRootBridgeIo;

+  if (Enable) {

+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);

+    //

+    // set the Rom base address: now is hardcode

+    //

+    PciRootBridgeIo->Pci.Write(

+                               PciRootBridgeIo, 

+                               EfiPciWidthUint32, 

+                               Address, 

+                               1, 

+                               &RomBar);

+  

+    //

+    // enable its decoder

+    //

+    Value32 = RomBar | 0x1;

+    PciRootBridgeIo->Pci.Write(

+                               PciRootBridgeIo, 

+                               EfiPciWidthUint32, 

+                               Address, 

+                               1, 

+                               &Value32);

+    

+    //

+    //setting the memory space bit in the function's command register

+    //

+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);

+    PciRootBridgeIo->Pci.Read(

+                              PciRootBridgeIo, 

+                              EfiPciWidthUint16, 

+                              Address, 

+                              1, 

+                              &CommandValue);

+    

+    CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003

+    PciRootBridgeIo->Pci.Write(

+                               PciRootBridgeIo, 

+                               EfiPciWidthUint16, 

+                               Address, 

+                               1, 

+                               &CommandValue);

+  } else {

+    //

+    // disable rom decode

+    //  

+    Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);

+    Value32 = 0xfffffffe;

+    PciRootBridgeIo->Pci.Write(

+                               PciRootBridgeIo, 

+                               EfiPciWidthUint32, 

+                               Address, 

+                               1, 

+                               &Value32);

+  }

+

+  return EFI_SUCCESS;

+

+}

+

+EFI_STATUS

+ProcessOpRomImage (

+  PCI_IO_DEVICE   *PciDevice

+  )

+/*++

+

+Routine Description:

+

+  Process the oprom image.

+  

+Arguments:

+  PciDevice       A pointer to a pci device.

+

+Returns:

+

+  EFI Status.

+  

+--*/

+{

+  UINT8                         Indicator;

+  UINT32                        ImageSize;

+  UINT16                        ImageOffset;

+  VOID                          *RomBar;

+  UINT8                         *RomBarOffset;

+  EFI_HANDLE                    ImageHandle;

+  EFI_STATUS                    Status;

+  EFI_STATUS                    retStatus;

+  BOOLEAN                       SkipImage;

+  UINT32                        DestinationSize;

+  UINT32                        ScratchSize;

+  UINT8                         *Scratch;

+  VOID                          *ImageBuffer;

+  VOID                          *DecompressedImageBuffer;

+  UINT32                        ImageLength;

+  EFI_DECOMPRESS_PROTOCOL       *Decompress;

+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;

+  PCI_DATA_STRUCTURE            *Pcir;

+  UINT32                        InitializationSize;

+

+  Indicator = 0;

+

+  //

+  // Get the Address of the Rom image

+  //

+  RomBar        = PciDevice->PciIo.RomImage;

+  RomBarOffset  = (UINT8 *) RomBar;

+  retStatus     = EFI_NOT_FOUND;

+

+  if (RomBarOffset == NULL) {

+    return retStatus;

+  }

+  ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);

+

+  do {

+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;

+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {

+      RomBarOffset = RomBarOffset + 512;

+      continue;

+    }

+

+    Pcir        = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);

+    ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);

+    ImageSize   = (UINT32) (Pcir->ImageLength * 512);

+    Indicator   = Pcir->Indicator;

+

+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&

+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&

+        ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||

+         (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {

+

+      ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;

+      InitializationSize      = EfiRomHeader->InitializationSize * 512;

+

+      if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {

+

+        ImageBuffer             = (VOID *) (RomBarOffset + ImageOffset);

+        ImageLength             =  InitializationSize - (UINT32)ImageOffset;

+        DecompressedImageBuffer = NULL;

+

+        //

+        // decompress here if needed

+        //

+        SkipImage = FALSE;

+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {

+          SkipImage = TRUE;

+        }

+

+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {

+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);

+          if (EFI_ERROR (Status)) {

+            SkipImage = TRUE;

+          } else {

+            SkipImage = TRUE;

+            Status = Decompress->GetInfo (

+                                  Decompress,

+                                  ImageBuffer,

+                                  ImageLength,

+                                  &DestinationSize,

+                                  &ScratchSize

+                                  );

+            if (!EFI_ERROR (Status)) {

+              DecompressedImageBuffer = NULL;

+              DecompressedImageBuffer = AllocatePool (DestinationSize);

+              if (DecompressedImageBuffer != NULL) {

+                Scratch = AllocatePool (ScratchSize);

+                if (Scratch != NULL) {

+                  Status = Decompress->Decompress (

+                                        Decompress,

+                                        ImageBuffer,

+                                        ImageLength,

+                                        DecompressedImageBuffer,

+                                        DestinationSize,

+                                        Scratch,

+                                        ScratchSize

+                                        );

+                  if (!EFI_ERROR (Status)) {

+                    ImageBuffer = DecompressedImageBuffer;

+                    ImageLength = DestinationSize;

+                    SkipImage   = FALSE;

+                  }

+

+                  gBS->FreePool (Scratch);

+                }

+              }

+            }

+          }

+        }

+

+        if (!SkipImage) {

+          //

+          // load image and start image

+          //

+          Status = gBS->LoadImage (

+                          FALSE,

+                          gPciBusDriverBinding.DriverBindingHandle,

+                          NULL,

+                          ImageBuffer,

+                          ImageLength,

+                          &ImageHandle

+                          );

+          if (!EFI_ERROR (Status)) {

+            Status = gBS->StartImage (ImageHandle, NULL, NULL);

+            if (!EFI_ERROR (Status)) {

+              AddDriver (PciDevice, ImageHandle);

+              retStatus = EFI_SUCCESS;

+            }

+          }

+        }

+

+        RomBarOffset = RomBarOffset + ImageSize;

+      } else {

+        RomBarOffset = RomBarOffset + ImageSize;

+      }

+    } else {

+      RomBarOffset = RomBarOffset + ImageSize;

+    }

+

+  } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));

+

+  return retStatus;

+

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h
new file mode 100644
index 0000000..7128ec4
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.h
@@ -0,0 +1,92 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciOptionRomSupport.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_OP_ROM_SUPPORT_H

+#define _EFI_PCI_OP_ROM_SUPPORT_H

+

+EFI_STATUS

+GetOpRomInfo (

+  IN PCI_IO_DEVICE    *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+LoadOpRomImage (

+  IN PCI_IO_DEVICE   *PciDevice,

+  IN UINT64          ReservedMemoryBase

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciDevice - TODO: add argument description

+  RomBase   - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+EFI_STATUS

+ProcessOpRomImage (

+  PCI_IO_DEVICE   *PciDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c
new file mode 100644
index 0000000..eaeaeb7
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.c
@@ -0,0 +1,100 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciPowerManagement.c

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+EFI_STATUS

+EFIAPI

+ResetPowerManagementFeature (

+  IN PCI_IO_DEVICE *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  This function is intended to turn off PWE assertion and

+  put the device to D0 state if the device supports

+  PCI Power Management.

+

+Arguments:

+

+Returns:

+  

+  None

+

+--*/

+{

+  EFI_STATUS  Status;

+  UINT8       PowerManagementRegBlock;

+  UINT16      PowerManagementCSR;

+

+  PowerManagementRegBlock = 0;

+

+  Status = LocateCapabilityRegBlock (

+            PciIoDevice,

+            EFI_PCI_CAPABILITY_ID_PMI,

+            &PowerManagementRegBlock,

+            NULL

+            );

+

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Turn off the PWE assertion and put the device into D0 State

+  //

+

+  //

+  // Read PMCSR

+  //

+  Status = PciIoDevice->PciIo.Pci.Read (

+                                    &PciIoDevice->PciIo,

+                                    EfiPciIoWidthUint16,

+                                    PowerManagementRegBlock + 4,

+                                    1,

+                                    &PowerManagementCSR

+                                    );

+  if (!EFI_ERROR (Status)) {

+    //

+    // Clear PME_Status bit

+    //

+    PowerManagementCSR |= BIT15;

+    //

+    // Clear PME_En bit. PowerState = D0.

+    //

+    PowerManagementCSR &= ~(BIT8 | BIT1 | BIT0);

+

+    //

+    // Write PMCSR

+    //

+    Status = PciIoDevice->PciIo.Pci.Write (

+                                      &PciIoDevice->PciIo,

+                                      EfiPciIoWidthUint16,

+                                      PowerManagementRegBlock + 4,

+                                      1,

+                                      &PowerManagementCSR

+                                      );

+  }

+  return Status;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h
new file mode 100644
index 0000000..e53303b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciPowerManagement.h
@@ -0,0 +1,49 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciPowerManagement.h

+  

+Abstract:

+

+  PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_POWER_MANAGEMENT_H

+#define _EFI_PCI_POWER_MANAGEMENT_H

+

+EFI_STATUS

+EFIAPI

+ResetPowerManagementFeature (

+  IN PCI_IO_DEVICE *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  PciIoDevice - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c
new file mode 100644
index 0000000..5085431
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c
@@ -0,0 +1,393 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciRomTable.c

+  

+Abstract:

+

+  Option Rom Support for PCI Bus Driver

+

+Revision History

+

+--*/

+

+#include "PciBus.h"

+

+typedef struct {

+  EFI_HANDLE  ImageHandle;

+  UINTN       Seg;

+  UINT8       Bus;

+  UINT8       Dev;

+  UINT8       Func;

+} EFI_PCI_ROM_IMAGE_MAPPING;

+

+UINTN                      mNumberOfPciRomImages     = 0;

+UINTN                      mMaxNumberOfPciRomImages  = 0;

+EFI_PCI_ROM_IMAGE_MAPPING  *mRomImageTable           = NULL;

+

+CHAR16 mHexDigit[17] = L"0123456789ABCDEF";

+

+VOID

+PciRomAddImageMapping (

+  IN EFI_HANDLE  ImageHandle,

+  IN UINTN       Seg,

+  IN UINT8       Bus,

+  IN UINT8       Dev,

+  IN UINT8       Func

+  )

+

+{

+  EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;

+

+  if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {

+

+    mMaxNumberOfPciRomImages += 0x20;

+

+    TempMapping = NULL;

+    TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));

+    if (TempMapping == NULL) {

+      return ;

+    }

+

+    CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));

+

+    if (mRomImageTable != NULL) {

+      gBS->FreePool (mRomImageTable);

+    }

+

+    mRomImageTable = TempMapping;

+  }

+

+  mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;

+  mRomImageTable[mNumberOfPciRomImages].Seg         = Seg;

+  mRomImageTable[mNumberOfPciRomImages].Bus         = Bus;

+  mRomImageTable[mNumberOfPciRomImages].Dev         = Dev;

+  mRomImageTable[mNumberOfPciRomImages].Func        = Func;

+  mNumberOfPciRomImages++;

+}

+

+VOID

+HexToString (

+  CHAR16  *String,

+  UINTN   Value,

+  UINTN   Digits

+  )

+

+{

+  for (; Digits > 0; Digits--, String++) {

+    *String = mHexDigit[((Value >> (4*(Digits-1))) & 0x0f)];

+  }

+}

+

+EFI_STATUS

+PciRomLoadEfiDriversFromRomImage (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_PCI_OPTION_ROM_DESCRIPTOR  *PciOptionRomDescriptor

+  )

+/*++

+

+Routine Description:

+  Command entry point. 

+

+Arguments:

+  ImageHandle     The image handle. 

+  SystemTable     The system table.

+

+Returns:

+  EFI_SUCCESS             - The command completed successfully

+  EFI_INVALID_PARAMETER   - Command usage error

+  EFI_UNSUPPORTED         - Protocols unsupported

+  EFI_OUT_OF_RESOURCES    - Out of memory

+  Other value             - Unknown error

+

+--*/

+{

+  VOID                          *RomBar;

+  UINTN                         RomSize;

+  CHAR16                        *FileName;

+  EFI_PCI_EXPANSION_ROM_HEADER  *EfiRomHeader;

+  PCI_DATA_STRUCTURE            *Pcir;

+  UINTN                         ImageIndex;

+  UINTN                         RomBarOffset;

+  UINT32                        ImageSize;

+  UINT16                        ImageOffset;

+  EFI_HANDLE                    ImageHandle;

+  EFI_STATUS                    Status;

+  EFI_STATUS                    retStatus;

+  EFI_DEVICE_PATH_PROTOCOL      *FilePath;

+  BOOLEAN                       SkipImage;

+  UINT32                        DestinationSize;

+  UINT32                        ScratchSize;

+  UINT8                         *Scratch;

+  VOID                          *ImageBuffer;

+  VOID                          *DecompressedImageBuffer;

+  UINT32                        ImageLength;

+  EFI_DECOMPRESS_PROTOCOL       *Decompress;

+  UINT32                        InitializationSize;

+

+  RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;

+  RomSize = (UINTN) PciOptionRomDescriptor->RomLength;

+  FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";

+

+  HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);

+  HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);

+  HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);

+  HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);

+

+  ImageIndex    = 0;

+  retStatus     = EFI_NOT_FOUND;

+  RomBarOffset  = (UINTN) RomBar;

+

+  do {

+

+    EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;

+

+

+    if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {

+      return retStatus;

+    }

+

+    //

+    // If the pointer to the PCI Data Structure is invalid, no further images can be located. 

+    // The PCI Data Structure must be DWORD aligned. 

+    //

+    if (EfiRomHeader->PcirOffset == 0 ||

+        (EfiRomHeader->PcirOffset & 3) != 0 ||

+        RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {

+      break;

+    }

+    Pcir      = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);

+    //

+    // If a valid signature is not present in the PCI Data Structure, no further images can be located.

+    //

+    if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {

+      break;

+    }

+    ImageSize = Pcir->ImageLength * 512;

+    if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {

+      break;

+    }

+

+    if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&

+        (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&

+        ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||

+         (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {

+

+      ImageOffset             = EfiRomHeader->EfiImageHeaderOffset;

+      InitializationSize      = EfiRomHeader->InitializationSize * 512;

+

+      if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {

+

+        ImageBuffer             = (VOID *) (UINTN) (RomBarOffset + ImageOffset);

+        ImageLength             = InitializationSize - ImageOffset;

+        DecompressedImageBuffer = NULL;

+

+        //

+        // decompress here if needed

+        //

+        SkipImage = FALSE;

+        if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {

+          SkipImage = TRUE;

+        }

+

+        if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {

+          Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);

+          if (EFI_ERROR (Status)) {

+            SkipImage = TRUE;

+          } else {

+            SkipImage = TRUE;

+            Status = Decompress->GetInfo (

+                                  Decompress,

+                                  ImageBuffer,

+                                  ImageLength,

+                                  &DestinationSize,

+                                  &ScratchSize

+                                  );

+            if (!EFI_ERROR (Status)) {

+              DecompressedImageBuffer = NULL;

+              DecompressedImageBuffer = AllocatePool (DestinationSize);

+              if (DecompressedImageBuffer != NULL) {

+                Scratch = AllocatePool (ScratchSize);

+                if (Scratch != NULL) {

+                  Status = Decompress->Decompress (

+                                        Decompress,

+                                        ImageBuffer,

+                                        ImageLength,

+                                        DecompressedImageBuffer,

+                                        DestinationSize,

+                                        Scratch,

+                                        ScratchSize

+                                        );

+                  if (!EFI_ERROR (Status)) {

+                    ImageBuffer = DecompressedImageBuffer;

+                    ImageLength = DestinationSize;

+                    SkipImage   = FALSE;

+                  }

+

+                  gBS->FreePool (Scratch);

+                }

+              }

+            }

+          }

+        }

+

+        if (!SkipImage) {

+

+          //

+          // load image and start image

+          //

+

+          HexToString (&FileName[48], ImageIndex, 4);

+          FilePath = FileDevicePath (NULL, FileName);

+

+          Status = gBS->LoadImage (

+                          FALSE,

+                          This->ImageHandle,

+                          FilePath,

+                          ImageBuffer,

+                          ImageLength,

+                          &ImageHandle

+                          );

+          if (!EFI_ERROR (Status)) {

+            Status = gBS->StartImage (ImageHandle, NULL, NULL);

+            if (!EFI_ERROR (Status)) {

+              PciRomAddImageMapping (

+                ImageHandle,

+                PciOptionRomDescriptor->Seg,

+                PciOptionRomDescriptor->Bus,

+                PciOptionRomDescriptor->Dev,

+                PciOptionRomDescriptor->Func

+                );

+              retStatus = Status;

+            }

+          }

+          if (FilePath != NULL) {

+            gBS->FreePool (FilePath);

+          }

+        }

+

+        if (DecompressedImageBuffer != NULL) {

+          gBS->FreePool (DecompressedImageBuffer);

+        }

+

+      }

+    }

+

+    RomBarOffset = RomBarOffset + ImageSize;

+    ImageIndex++;

+  } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));

+

+  return retStatus;

+}

+

+EFI_STATUS

+PciRomLoadEfiDriversFromOptionRomTable (

+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  EFI_STATUS                        Status;

+  EFI_PCI_OPTION_ROM_TABLE          *PciOptionRomTable;

+  EFI_PCI_OPTION_ROM_DESCRIPTOR     *PciOptionRomDescriptor;

+  UINTN                             Index;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;

+  UINT16                            MinBus;

+  UINT16                            MaxBus;

+

+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);

+  if (EFI_ERROR (Status)) {

+    return EFI_NOT_FOUND;

+  }

+

+  Status = EFI_NOT_FOUND;

+

+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {

+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];

+    if (!PciOptionRomDescriptor->DontLoadEfiRom) {

+      if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {

+        Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);

+        if (EFI_ERROR (Status)) {

+          return Status;

+        }

+

+        PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);

+        if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {

+          Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);

+          PciOptionRomDescriptor->DontLoadEfiRom |= 2;

+        }

+      }

+    }

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+PciRomGetRomResourceFromPciOptionRomTable (

+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  PCI_IO_DEVICE                       *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+--*/

+{

+  EFI_STATUS                    Status;

+  EFI_PCI_OPTION_ROM_TABLE      *PciOptionRomTable;

+  EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;

+  UINTN                         Index;

+

+  Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);

+  if (EFI_ERROR (Status)) {

+    return EFI_NOT_FOUND;

+  }

+

+  for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {

+    PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];

+    if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&

+        PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber         &&

+        PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber      &&

+        PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {

+

+      PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;

+      PciIoDevice->PciIo.RomSize  = (UINTN) PciOptionRomDescriptor->RomLength;

+    }

+  }

+

+  for (Index = 0; Index < mNumberOfPciRomImages; Index++) {

+    if (mRomImageTable[Index].Seg  == PciRootBridgeIo->SegmentNumber &&

+        mRomImageTable[Index].Bus  == PciIoDevice->BusNumber         &&

+        mRomImageTable[Index].Dev  == PciIoDevice->DeviceNumber      &&

+        mRomImageTable[Index].Func == PciIoDevice->FunctionNumber    ) {

+

+      AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);

+    }

+  }

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h
new file mode 100644
index 0000000..159a7f3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciBusNoEnumerationDxe/PciRomTable.h
@@ -0,0 +1,58 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  PciRomTable.h

+  

+Abstract:

+

+  Option Rom Support for PCI Bus Driver

+

+Revision History

+

+--*/

+

+#ifndef _EFI_PCI_ROM_TABLE_H

+#define _EFI_PCI_ROM_TABLE_H

+

+

+EFI_STATUS

+PciRomLoadEfiDriversFromOptionRomTable (

+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo

+  );

+

+EFI_STATUS

+PciRomGetRomResourceFromPciOptionRomTable (

+  IN EFI_DRIVER_BINDING_PROTOCOL      *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,

+  PCI_IO_DEVICE                       *PciIoDevice

+  )

+/*++

+

+Routine Description:

+

+  TODO: Add function description

+

+Arguments:

+

+  This            - TODO: add argument description

+  PciRootBridgeIo - TODO: add argument description

+  PciIoDevice     - TODO: add argument description

+

+Returns:

+

+  TODO: add return values

+

+--*/

+;

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c
new file mode 100644
index 0000000..b9cae2b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.c
@@ -0,0 +1,845 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    DeviceIo.c

+    

+Abstract:

+

+    EFI PC-AT PCI Device IO driver

+

+--*/

+#include "PcatPciRootBridge.h"

+#include "DeviceIo.h"

+

+EFI_STATUS

+DeviceIoConstructor (

+  IN EFI_HANDLE                      Handle,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,

+  IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,

+  IN UINT16                          PrimaryBus,

+  IN UINT16                          SubordinateBus

+  )

+/*++

+

+Routine Description:

+  

+  Initialize and install a Device IO protocol on a empty device path handle.

+

+Arguments:

+  

+  Handle               - Handle of PCI RootBridge IO instance

+  PciRootBridgeIo      - PCI RootBridge IO instance

+  DevicePath           - Device Path of PCI RootBridge IO instance

+  PrimaryBus           - Primary Bus

+  SubordinateBus       - Subordinate Bus

+

+Returns:

+  

+  EFI_SUCCESS          -  This driver is added to ControllerHandle.  

+  EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.   

+  Others               -  This driver does not support this device.

+

+--*/

+{

+  EFI_STATUS                      Status;

+  DEVICE_IO_PRIVATE_DATA          *Private;

+

+  //

+  // Initialize the Device IO device instance.

+  //

+  Private = AllocateZeroPool (sizeof (DEVICE_IO_PRIVATE_DATA));

+  if (Private == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Private->Signature                = DEVICE_IO_PRIVATE_DATA_SIGNATURE;

+  Private->Handle                   = Handle;

+  Private->PciRootBridgeIo          = PciRootBridgeIo;

+  Private->DevicePath               = DevicePath;

+  Private->PrimaryBus               = PrimaryBus;

+  Private->SubordinateBus           = SubordinateBus;

+

+  Private->DeviceIo.Mem.Read        = DeviceIoMemRead;

+  Private->DeviceIo.Mem.Write       = DeviceIoMemWrite;

+  Private->DeviceIo.Io.Read         = DeviceIoIoRead;

+  Private->DeviceIo.Io.Write        = DeviceIoIoWrite;

+  Private->DeviceIo.Pci.Read        = DeviceIoPciRead;

+  Private->DeviceIo.Pci.Write       = DeviceIoPciWrite;

+  Private->DeviceIo.PciDevicePath   = DeviceIoPciDevicePath;

+  Private->DeviceIo.Map             = DeviceIoMap;

+  Private->DeviceIo.Unmap           = DeviceIoUnmap;

+  Private->DeviceIo.AllocateBuffer  = DeviceIoAllocateBuffer;

+  Private->DeviceIo.Flush           = DeviceIoFlush;

+  Private->DeviceIo.FreeBuffer      = DeviceIoFreeBuffer;

+

+  //

+  // Install protocol interfaces for the Device IO device.

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &Private->Handle,

+                  &gEfiDeviceIoProtocolGuid,

+                  &Private->DeviceIo,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoMemRead (

+  IN     EFI_DEVICE_IO_PROTOCOL   *This,

+  IN     EFI_IO_WIDTH             Width,

+  IN     UINT64                   Address,

+  IN     UINTN                    Count,

+  IN OUT VOID                     *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading memory mapped I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations.  

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.           

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.  

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if (Width > MMIO_COPY_UINT64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (Width >= MMIO_COPY_UINT8) {

+    Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);

+    Status = Private->PciRootBridgeIo->CopyMem (

+                                         Private->PciRootBridgeIo,

+                                         (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                         (UINT64)(UINTN) Buffer,

+                                         Address,

+                                         Count

+                                         );

+  } else {

+    Status = Private->PciRootBridgeIo->Mem.Read (

+                                             Private->PciRootBridgeIo,

+                                             (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                             Address,

+                                             Count,

+                                             Buffer

+                                             );

+  }

+

+  return Status;

+}

+

+

+

+EFI_STATUS

+EFIAPI

+DeviceIoMemWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL    *This,

+  IN     EFI_IO_WIDTH              Width,

+  IN     UINT64                    Address,

+  IN     UINTN                     Count,

+  IN OUT VOID                      *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing memory mapped I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.  

+  Address  -  The base address of I/O operations.   

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.            

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if (Width > MMIO_COPY_UINT64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (Width >= MMIO_COPY_UINT8) {

+    Width = (EFI_IO_WIDTH) (Width - MMIO_COPY_UINT8);

+    Status = Private->PciRootBridgeIo->CopyMem (

+                                         Private->PciRootBridgeIo,

+                                         (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                         Address,

+                                         (UINT64)(UINTN) Buffer,

+                                         Count

+                                         );

+  } else {

+    Status = Private->PciRootBridgeIo->Mem.Write (

+                                             Private->PciRootBridgeIo,

+                                             (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                             Address,

+                                             Count,

+                                             Buffer

+                                             );

+  }

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoIoRead (

+  IN     EFI_DEVICE_IO_PROTOCOL   *This,

+  IN     EFI_IO_WIDTH             Width,

+  IN     UINT64                   Address,

+  IN     UINTN                    Count,

+  IN OUT VOID                     *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.          

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if (Width >= MMIO_COPY_UINT8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = Private->PciRootBridgeIo->Io.Read (

+                                          Private->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                          Address,

+                                          Count,

+                                          Buffer

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoIoWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL    *This,

+  IN     EFI_IO_WIDTH              Width,

+  IN     UINT64                    Address,

+  IN     UINTN                     Count,

+  IN OUT VOID                      *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations.

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.        

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if (Width >= MMIO_COPY_UINT8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = Private->PciRootBridgeIo->Io.Write (

+                                          Private->PciRootBridgeIo,

+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                          Address,

+                                          Count,

+                                          Buffer

+                                          );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciRead (

+  IN     EFI_DEVICE_IO_PROTOCOL   *This,

+  IN     EFI_IO_WIDTH             Width,

+  IN     UINT64                   Address,

+  IN     UINTN                    Count,

+  IN OUT VOID                     *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading PCI configuration space of device

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations. 

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.           

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if ((UINT32)Width >= MMIO_COPY_UINT8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = Private->PciRootBridgeIo->Pci.Read (

+                                           Private->PciRootBridgeIo,

+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                           Address,

+                                           Count,

+                                           Buffer

+                                           );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL    *This,

+  IN     EFI_IO_WIDTH              Width,

+  IN     UINT64                    Address,

+  IN     UINTN                     Count,

+  IN OUT VOID                      *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing PCI configuration space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.   

+  Width    -  Width of I/O operations. 

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.         

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if ((UINT32)Width >= MMIO_COPY_UINT8) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status = Private->PciRootBridgeIo->Pci.Write (

+                                           Private->PciRootBridgeIo,

+                                           (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,

+                                           Address,

+                                           Count,

+                                           Buffer

+                                           );

+

+  return Status;

+}

+

+EFI_DEVICE_PATH_PROTOCOL *

+AppendPciDevicePath (

+  IN     DEVICE_IO_PRIVATE_DATA    *Private,

+  IN     UINT8                     Bus,

+  IN     UINT8                     Device,

+  IN     UINT8                     Function,

+  IN     EFI_DEVICE_PATH_PROTOCOL  *DevicePath,

+  IN OUT UINT16                    *BridgePrimaryBus,

+  IN OUT UINT16                    *BridgeSubordinateBus

+  )

+/*++

+

+Routine Description:

+  

+  Append a PCI device path node to another device path.

+

+Arguments:

+  

+  Private               -  A pointer to DEVICE_IO_PRIVATE_DATA instance.  

+  Bus                   -  PCI bus number of the device.

+  Device                -  PCI device number of the device.

+  Function              -  PCI function number of the device.

+  DevicePath            -  Original device path which will be appended a PCI device path node.

+  BridgePrimaryBus      -  Primary bus number of the bridge.

+  BridgeSubordinateBus  -  Subordinate bus number of the bridge.

+

+Returns:

+  

+  Pointer to the appended PCI device path.

+

+--*/

+{

+  UINT16                    ThisBus;

+  UINT8                     ThisDevice;

+  UINT8                     ThisFunc;

+  UINT64                    Address;

+  PCI_TYPE01                PciBridge;

+  PCI_TYPE01                *PciPtr;

+  EFI_DEVICE_PATH_PROTOCOL  *ReturnDevicePath;

+  PCI_DEVICE_PATH           PciNode;

+

+  PciPtr = &PciBridge;

+  for (ThisBus = *BridgePrimaryBus; ThisBus <= *BridgeSubordinateBus; ThisBus++) {

+    for (ThisDevice = 0; ThisDevice <= PCI_MAX_DEVICE; ThisDevice++) {

+      for (ThisFunc = 0; ThisFunc <= PCI_MAX_FUNC; ThisFunc++) {

+        Address = EFI_PCI_ADDRESS (ThisBus, ThisDevice, ThisFunc, 0);

+        ZeroMem (PciPtr, sizeof (PCI_TYPE01));

+        Private->DeviceIo.Pci.Read (

+                                &Private->DeviceIo,

+                                IO_UINT32,

+                                Address,

+                                1,

+                                &(PciPtr->Hdr.VendorId)

+                                );

+        if ((PciPtr->Hdr.VendorId == 0xffff) && (ThisFunc == 0)) {

+          break;

+        }

+        if (PciPtr->Hdr.VendorId == 0xffff) {

+          continue;

+        }

+

+        Private->DeviceIo.Pci.Read (

+                                &Private->DeviceIo,

+                                IO_UINT32,

+                                Address,

+                                sizeof (PCI_TYPE01) / sizeof (UINT32),

+                                PciPtr

+                                );

+        if (IS_PCI_BRIDGE (PciPtr)) {

+          if (Bus >= PciPtr->Bridge.SecondaryBus && Bus <= PciPtr->Bridge.SubordinateBus) {

+

+            PciNode.Header.Type     = HARDWARE_DEVICE_PATH;

+            PciNode.Header.SubType  = HW_PCI_DP;

+            SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));

+

+            PciNode.Device        = ThisDevice;

+            PciNode.Function      = ThisFunc;

+            ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);

+

+            *BridgePrimaryBus     = PciPtr->Bridge.SecondaryBus;

+            *BridgeSubordinateBus = PciPtr->Bridge.SubordinateBus;

+            return ReturnDevicePath;

+          }

+        }

+

+        if ((ThisFunc == 0) && ((PciPtr->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x0)) {

+          //

+          // Skip sub functions, this is not a multi function device

+          //

+          break;

+        }

+      }

+    }

+  }

+

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

+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;

+  PciNode.Header.SubType  = HW_PCI_DP;

+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));

+  PciNode.Device        = Device;

+  PciNode.Function      = Function;

+

+  ReturnDevicePath      = AppendDevicePathNode (DevicePath, &PciNode.Header);

+

+  *BridgePrimaryBus     = 0xffff;

+  *BridgeSubordinateBus = 0xffff;

+  return ReturnDevicePath;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciDevicePath (

+  IN     EFI_DEVICE_IO_PROTOCOL        *This,

+  IN     UINT64                        Address,

+  IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath

+  )

+/*++

+

+Routine Description:

+  

+  Provides an EFI Device Path for a PCI device with the given PCI configuration space address.

+

+Arguments:

+  

+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.  

+  Address        -  The PCI configuration space address of the device whose Device Path

+                    is going to be returned.           

+  PciDevicePath  -  A pointer to the pointer for the EFI Device Path for PciAddress.

+                    Memory for the Device Path is allocated from the pool.

+

+Returns:

+  

+  EFI_SUCCESS           -  The PciDevicePath returns a pointer to a valid EFI Device Path.

+  EFI_UNSUPPORTED       -  The PciAddress does not map to a valid EFI Device Path. 

+  EFI_OUT_OF_RESOURCES  -  The request could not be completed due to a lack of resources.

+

+--*/

+{

+  DEVICE_IO_PRIVATE_DATA  *Private;

+  UINT16                  PrimaryBus;

+  UINT16                  SubordinateBus;

+  UINT8                   Bus;

+  UINT8                   Device;

+  UINT8                   Func;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  Bus     = (UINT8) (((UINT32) Address >> 24) & 0xff);

+  Device  = (UINT8) (((UINT32) Address >> 16) & 0xff);

+  Func    = (UINT8) (((UINT32) Address >> 8) & 0xff);

+

+  if (Bus < Private->PrimaryBus || Bus > Private->SubordinateBus) {

+    return EFI_UNSUPPORTED;

+  }

+

+  *PciDevicePath  = Private->DevicePath;

+  PrimaryBus      = Private->PrimaryBus;

+  SubordinateBus  = Private->SubordinateBus;

+  do {

+    *PciDevicePath = AppendPciDevicePath (

+                       Private,

+                       Bus,

+                       Device,

+                       Func,

+                       *PciDevicePath,

+                       &PrimaryBus,

+                       &SubordinateBus

+                       );

+    if (*PciDevicePath == NULL) {

+      return EFI_OUT_OF_RESOURCES;

+    }

+  } while (PrimaryBus != 0xffff);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoMap (

+  IN     EFI_DEVICE_IO_PROTOCOL   *This,

+  IN     EFI_IO_OPERATION_TYPE    Operation,

+  IN     EFI_PHYSICAL_ADDRESS     *HostAddress,

+  IN OUT UINTN                    *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,

+  OUT    VOID                     **Mapping

+  )

+/*++

+

+Routine Description:

+  

+  Provides the device-specific addresses needed to access system memory.

+

+Arguments:

+  

+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance. 

+  Operation      -  Indicates if the bus master is going to read or write to system memory.  

+  HostAddress    -  The system memory address to map to the device.

+  NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes

+                    that were mapped.

+  DeviceAddress  -  The resulting map address for the bus master device to use to access the

+                    hosts HostAddress.

+  Mapping        -  A resulting value to pass to Unmap().

+

+Returns:

+  

+  EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes. 

+  EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined. 

+  EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.

+  EFI_DEVICE_ERROR       -  The system hardware could not map the requested address. 

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  if ((UINT32)Operation > EfiBusMasterCommonBuffer) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (((UINTN) (*HostAddress) != (*HostAddress)) && Operation == EfiBusMasterCommonBuffer) {

+    return EFI_UNSUPPORTED;

+  }

+

+  Status = Private->PciRootBridgeIo->Map (

+                                       Private->PciRootBridgeIo,

+                                       (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,

+                                       (VOID *) (UINTN) (*HostAddress),

+                                       NumberOfBytes,

+                                       DeviceAddress,

+                                       Mapping

+                                       );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoUnmap (

+  IN EFI_DEVICE_IO_PROTOCOL   *This,

+  IN VOID                     *Mapping

+  )

+/*++

+

+Routine Description:

+  

+  Completes the Map() operation and releases any corresponding resources.

+

+Arguments:

+  

+  This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Mapping  -  The mapping value returned from Map().

+

+Returns:

+  

+  EFI_SUCCESS       -  The range was unmapped.

+  EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  Status = Private->PciRootBridgeIo->Unmap (

+                                       Private->PciRootBridgeIo,

+                                       Mapping

+                                       );

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoAllocateBuffer (

+  IN     EFI_DEVICE_IO_PROTOCOL    *This,

+  IN     EFI_ALLOCATE_TYPE         Type,

+  IN     EFI_MEMORY_TYPE           MemoryType,

+  IN     UINTN                     Pages,

+  IN OUT EFI_PHYSICAL_ADDRESS      *PhysicalAddress

+  )

+/*++

+

+Routine Description:

+  

+  Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.

+

+Arguments:

+  

+  This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Type             -  The type allocation to perform.

+  MemoryType       -  The type of memory to allocate, EfiBootServicesData or

+                      EfiRuntimeServicesData.

+  Pages            -  The number of pages to allocate.

+  PhysicalAddress  -  A pointer to store the base address of the allocated range.

+

+Returns:

+  

+  EFI_SUCCESS            -  The requested memory pages were allocated.

+  EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.

+  EFI_INVALID_PARAMETER  -  The requested memory type is invalid.

+  EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on

+                            this platform.

+

+--*/

+{

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  HostAddress;

+

+  HostAddress = *PhysicalAddress;

+

+  if ((MemoryType != EfiBootServicesData) && (MemoryType != EfiRuntimeServicesData)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((UINT32)Type >= MaxAllocateType) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Type == AllocateAddress) && (HostAddress + EFI_PAGES_TO_SIZE (Pages) - 1 > MAX_COMMON_BUFFER)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if ((AllocateAnyPages == Type) || (AllocateMaxAddress == Type && HostAddress > MAX_COMMON_BUFFER)) {

+    Type        = AllocateMaxAddress;

+    HostAddress = MAX_COMMON_BUFFER;

+  }

+

+  Status = gBS->AllocatePages (

+                  Type,

+                  MemoryType,

+                  Pages,

+                  &HostAddress

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+

+  *PhysicalAddress = HostAddress;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoFlush (

+  IN EFI_DEVICE_IO_PROTOCOL  *This

+  )

+/*++

+

+Routine Description:

+  

+  Flushes any posted write data to the device.

+

+Arguments:

+  

+  This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+

+Returns:

+  

+  EFI_SUCCESS       -  The buffers were flushed.

+  EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.

+

+--*/

+{

+  EFI_STATUS              Status;

+  DEVICE_IO_PRIVATE_DATA  *Private;

+

+  Private = DEVICE_IO_PRIVATE_DATA_FROM_THIS (This);

+

+  Status  = Private->PciRootBridgeIo->Flush (Private->PciRootBridgeIo);

+

+  return Status;

+}

+

+EFI_STATUS

+EFIAPI

+DeviceIoFreeBuffer (

+  IN EFI_DEVICE_IO_PROTOCOL   *This,

+  IN UINTN                    Pages,

+  IN EFI_PHYSICAL_ADDRESS     HostAddress

+  )

+/*++

+

+Routine Description:

+  

+  Frees pages that were allocated with AllocateBuffer().

+

+Arguments:

+  

+  This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Pages        -  The number of pages to free.

+  HostAddress  -  The base address of the range to free.

+

+Returns:

+  

+  EFI_SUCCESS            -  The requested memory pages were freed.

+  EFI_NOT_FOUND          -  The requested memory pages were not allocated with

+                            AllocateBuffer().               

+  EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.

+

+--*/

+{

+  if (((HostAddress & EFI_PAGE_MASK) != 0) || (Pages <= 0)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return gBS->FreePages (HostAddress, Pages);

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h
new file mode 100644
index 0000000..6c40f9d
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/DeviceIo.h
@@ -0,0 +1,449 @@
+/*++

+

+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+    DeviceIo.h

+    

+Abstract:

+

+    Private Data definition for Device IO driver

+

+--*/

+

+#ifndef _DEVICE_IO_H

+#define _DEVICE_IO_H

+

+

+

+#define DEVICE_IO_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('d', 'e', 'v', 'I')

+

+#define MAX_COMMON_BUFFER                 0x00000000FFFFFFFF

+

+typedef struct {

+  UINTN                           Signature;

+  EFI_HANDLE                      Handle;

+  EFI_DEVICE_IO_PROTOCOL          DeviceIo;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;

+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;

+  UINT16                          PrimaryBus;

+  UINT16                          SubordinateBus;

+} DEVICE_IO_PRIVATE_DATA;

+

+#define DEVICE_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DEVICE_IO_PRIVATE_DATA, DeviceIo, DEVICE_IO_PRIVATE_DATA_SIGNATURE)

+

+EFI_STATUS

+DeviceIoConstructor (

+  IN EFI_HANDLE                      Handle,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,

+  IN EFI_DEVICE_PATH_PROTOCOL        *DevicePath,

+  IN UINT16                          PrimaryBus,

+  IN UINT16                          SubordinateBus

+  )

+/*++

+

+Routine Description:

+

+  Initialize and install a Device IO protocol on a empty device path handle.

+

+Arguments:

+

+  Handle               - Handle of PCI RootBridge IO instance

+  PciRootBridgeIo      - PCI RootBridge IO instance

+  DevicePath           - Device Path of PCI RootBridge IO instance

+  PrimaryBus           - Primary Bus

+  SubordinateBus       - Subordinate Bus

+

+Returns:

+

+  EFI_SUCCESS          -  This driver is added to ControllerHandle.  

+  EFI_ALREADY_STARTED  -  This driver is already running on ControllerHandle.   

+  Others               -  This driver does not support this device.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoMemRead (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading memory mapped I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations.  

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.           

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.  

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoMemWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing memory mapped I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.  

+  Address  -  The base address of I/O operations.   

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.            

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoIoRead (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.          

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoIoWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing I/O space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations.

+  Address  -  The base address of I/O operations.

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.        

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciRead (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform reading PCI configuration space of device

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.  

+  Width    -  Width of I/O operations. 

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.           

+  Buffer   -  The destination buffer to store results.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was read from the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciWrite (

+  IN     EFI_DEVICE_IO_PROTOCOL *This,

+  IN     EFI_IO_WIDTH           Width,

+  IN     UINT64                 Address,

+  IN     UINTN                  Count,

+  IN OUT VOID                   *Buffer

+  )

+/*++

+

+Routine Description:

+  

+  Perform writing PCI configuration space of device.

+

+Arguments:

+  

+  This     -  A pointer to EFI_DEVICE_IO protocol instance.   

+  Width    -  Width of I/O operations. 

+  Address  -  The base address of I/O operations. 

+  Count    -  The number of I/O operations to perform. 

+              Bytes moves is Width size * Count, starting at Address.         

+  Buffer   -  The source buffer of data to be written.

+

+Returns:

+    

+  EFI_SUCCESS            -  The data was written to the device.

+  EFI_INVALID_PARAMETER  -  Width is invalid.

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoPciDevicePath (

+  IN     EFI_DEVICE_IO_PROTOCOL        *This,

+  IN     UINT64                        Address,

+  IN OUT EFI_DEVICE_PATH_PROTOCOL      **PciDevicePath

+  )

+/*++

+

+Routine Description:

+  

+  Append a PCI device path node to another device path.

+

+Arguments:

+  

+  This                  -  A pointer to EFI_DEVICE_IO_PROTOCOL.  

+  Address               -  PCI bus,device, function.

+  PciDevicePath         -  PCI device path.

+

+Returns:

+  

+  Pointer to the appended PCI device path.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoMap (

+  IN     EFI_DEVICE_IO_PROTOCOL   *This,

+  IN     EFI_IO_OPERATION_TYPE    Operation,

+  IN     EFI_PHYSICAL_ADDRESS     *HostAddress,

+  IN OUT UINTN                    *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS     *DeviceAddress,

+  OUT    VOID                     **Mapping

+  )

+/*++

+

+Routine Description:

+  

+  Provides the device-specific addresses needed to access system memory.

+

+Arguments:

+  

+  This           -  A pointer to the EFI_DEVICE_IO_INTERFACE instance. 

+  Operation      -  Indicates if the bus master is going to read or write to system memory.  

+  HostAddress    -  The system memory address to map to the device.

+  NumberOfBytes  -  On input the number of bytes to map. On output the number of bytes

+                    that were mapped.

+  DeviceAddress  -  The resulting map address for the bus master device to use to access the

+                    hosts HostAddress.

+  Mapping        -  A resulting value to pass to Unmap().

+

+Returns:

+  

+  EFI_SUCCESS            -  The range was mapped for the returned NumberOfBytes. 

+  EFI_INVALID_PARAMETER  -  The Operation or HostAddress is undefined. 

+  EFI_UNSUPPORTED        -  The HostAddress cannot be mapped as a common buffer.

+  EFI_DEVICE_ERROR       -  The system hardware could not map the requested address. 

+  EFI_OUT_OF_RESOURCES   -  The request could not be completed due to a lack of resources.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoUnmap (

+  IN EFI_DEVICE_IO_PROTOCOL   *This,

+  IN VOID                     *Mapping

+  )

+/*++

+

+Routine Description:

+  

+  Completes the Map() operation and releases any corresponding resources.

+

+Arguments:

+  

+  This     -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Mapping  -  The mapping value returned from Map().

+

+Returns:

+  

+  EFI_SUCCESS       -  The range was unmapped.

+  EFI_DEVICE_ERROR  -  The data was not committed to the target system memory.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoAllocateBuffer (

+  IN     EFI_DEVICE_IO_PROTOCOL    *This,

+  IN     EFI_ALLOCATE_TYPE         Type,

+  IN     EFI_MEMORY_TYPE           MemoryType,

+  IN     UINTN                     Pages,

+  IN OUT EFI_PHYSICAL_ADDRESS      *HostAddress

+  )

+/*++

+

+Routine Description:

+  

+  Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping.

+

+Arguments:

+  

+  This             -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Type             -  The type allocation to perform.

+  MemoryType       -  The type of memory to allocate, EfiBootServicesData or

+                      EfiRuntimeServicesData.

+  Pages            -  The number of pages to allocate.

+  HostAddress      -  A pointer to store the base address of the allocated range.

+

+Returns:

+  

+  EFI_SUCCESS            -  The requested memory pages were allocated.

+  EFI_OUT_OF_RESOURCES   -  The memory pages could not be allocated.

+  EFI_INVALID_PARAMETER  -  The requested memory type is invalid.

+  EFI_UNSUPPORTED        -  The requested PhysicalAddress is not supported on

+                            this platform.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoFlush (

+  IN EFI_DEVICE_IO_PROTOCOL  *This

+  )

+/*++

+

+Routine Description:

+  

+  Flushes any posted write data to the device.

+

+Arguments:

+  

+  This  -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+

+Returns:

+  

+  EFI_SUCCESS       -  The buffers were flushed.

+  EFI_DEVICE_ERROR  -  The buffers were not flushed due to a hardware error.

+

+--*/

+;

+

+EFI_STATUS

+EFIAPI

+DeviceIoFreeBuffer (

+  IN EFI_DEVICE_IO_PROTOCOL   *This,

+  IN UINTN                    Pages,

+  IN EFI_PHYSICAL_ADDRESS     HostAddress

+  )

+/*++

+

+Routine Description:

+  

+  Frees pages that were allocated with AllocateBuffer().

+

+Arguments:

+  

+  This         -  A pointer to the EFI_DEVICE_IO_INTERFACE instance.

+  Pages        -  The number of pages to free.

+  HostAddress  -  The base address of the range to free.

+

+Returns:

+  

+  EFI_SUCCESS            -  The requested memory pages were freed.

+  EFI_NOT_FOUND          -  The requested memory pages were not allocated with

+                            AllocateBuffer().               

+  EFI_INVALID_PARAMETER  -  HostAddress is not page aligned or Pages is invalid.

+

+--*/

+;

+

+#endif

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c
new file mode 100644
index 0000000..d479e7f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ia32/PcatIo.c
@@ -0,0 +1,738 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+    PcatPciRootBridgeIo.c

+    

+Abstract:

+

+    EFI PC AT PCI Root Bridge Io Protocol

+

+Revision History

+

+--*/

+

+#include "PcatPciRootBridge.h"

+

+BOOLEAN                  mPciOptionRomTableInstalled = FALSE;

+EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable          = {0, NULL};

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *UserBuffer

+  )

+{

+  return gCpuIo->Io.Read (

+                      gCpuIo,

+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,

+                      UserAddress,

+                      Count,

+                      UserBuffer

+                      );

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoWrite (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  )

+{

+  return gCpuIo->Io.Write (

+                      gCpuIo,

+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,

+                      UserAddress,

+                      Count,

+                      UserBuffer

+                      );

+

+}

+

+EFI_STATUS

+PcatRootBridgeIoGetIoPortMapping (

+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,

+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping

+  )

+/*++

+

+  Get the IO Port Mapping.  For IA-32 it is always 0.

+  

+--*/

+{

+  *IoPortMapping = 0;

+  *MemoryPortMapping = 0;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PcatRootBridgeIoPciRW (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN BOOLEAN                                Write,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  )

+{

+  PCI_CONFIG_ACCESS_CF8             Pci;

+  PCI_CONFIG_ACCESS_CF8             PciAligned;

+  UINT32                            InStride;

+  UINT32                            OutStride;

+  UINTN                             PciData;

+  UINTN                             PciDataStride;

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;

+  UINT64                            PciExpressRegAddr;

+  BOOLEAN                           UsePciExpressAccess;

+

+  if ((UINT32)Width >= EfiPciWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  if ((Width & 0x03) >= EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  InStride    = 1 << (Width & 0x03);

+  OutStride   = InStride;

+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    InStride = 0;

+  }

+

+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    OutStride = 0;

+  }

+

+  UsePciExpressAccess = FALSE;

+

+  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));

+

+  if (PciAddress.ExtendedRegister > 0xFF) {

+    //

+    // Check PciExpressBaseAddress

+    //

+    if ((PrivateData->PciExpressBaseAddress == 0) ||

+        (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {

+      return EFI_UNSUPPORTED;

+    } else {

+      UsePciExpressAccess = TRUE;

+    }

+  } else {

+    if (PciAddress.ExtendedRegister != 0) {

+      Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;

+    } else {

+      Pci.Bits.Reg = PciAddress.Register;

+    }

+    //

+    // Note: We can also use PciExpress access here, if wanted.

+    //

+  }

+

+  if (!UsePciExpressAccess) {

+    Pci.Bits.Func     = PciAddress.Function;

+    Pci.Bits.Dev      = PciAddress.Device;

+    Pci.Bits.Bus      = PciAddress.Bus;

+    Pci.Bits.Reserved = 0;

+    Pci.Bits.Enable   = 1;

+

+    //

+    // PCI Config access are all 32-bit alligned, but by accessing the

+    //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types

+    //  are possible on PCI.

+    //

+    // To read a byte of PCI config space you load 0xcf8 and 

+    //  read 0xcfc, 0xcfd, 0xcfe, 0xcff

+    //

+    PciDataStride = Pci.Bits.Reg & 0x03;

+

+    while (Count) {

+      PciAligned = Pci;

+      PciAligned.Bits.Reg &= 0xfc;

+      PciData = (UINTN)PrivateData->PciData + PciDataStride;

+      EfiAcquireLock(&PrivateData->PciLock);

+      This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);

+      if (Write) {

+        This->Io.Write (This, Width, PciData, 1, UserBuffer);

+      } else {

+        This->Io.Read (This, Width, PciData, 1, UserBuffer);

+      }

+      EfiReleaseLock(&PrivateData->PciLock);

+      UserBuffer = ((UINT8 *)UserBuffer) + OutStride;

+      PciDataStride = (PciDataStride + InStride) % 4;

+      Pci.Bits.Reg += InStride;

+      Count -= 1;

+    }

+  } else {

+    //

+    // Access PCI-Express space by using memory mapped method.

+    //

+    PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |

+                        (PciAddress.Bus      << 20) |

+                        (PciAddress.Device   << 15) |

+                        (PciAddress.Function << 12);

+    if (PciAddress.ExtendedRegister != 0) {

+      PciExpressRegAddr += PciAddress.ExtendedRegister;

+    } else {

+      PciExpressRegAddr += PciAddress.Register;

+    }

+    while (Count) {

+      if (Write) {

+        This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);

+      } else {

+        This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);

+      }

+

+      UserBuffer = ((UINT8 *) UserBuffer) + OutStride;

+      PciExpressRegAddr += InStride;

+      Count -= 1;

+    }

+  }

+  

+  return EFI_SUCCESS;

+}

+

+VOID

+ScanPciBus(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  EFI_PCI_BUS_SCAN_CALLBACK        Callback,

+  VOID                             *Context

+  )

+  

+{

+  UINT16      Bus;

+  UINT16      Device;

+  UINT16      Func;

+  UINT64      Address;

+  PCI_TYPE00  PciHeader;

+

+  //

+  // Loop through all busses

+  //

+  for (Bus = MinBus; Bus <= MaxBus; Bus++) {

+    //  

+    // Loop 32 devices per bus

+    //

+    for (Device = MinDevice; Device <= MaxDevice; Device++) {

+      //

+      // Loop through 8 functions per device

+      //

+      for (Func = MinFunc; Func <= MaxFunc; Func++) {

+

+        //

+        // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device

+        //

+        Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

+

+        //

+        // Read the VendorID from this PCI Device's Confioguration Header

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);

+    

+        //

+        // If VendorId = 0xffff, there does not exist a device at this 

+        // location. For each device, if there is any function on it, 

+        // there must be 1 function at Function 0. So if Func = 0, there

+        // will be no more functions in the same device, so we can break

+        // loop to deal with the next device.

+        //  

+        if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {

+          break;

+        }

+        

+        if (PciHeader.Hdr.VendorId != 0xffff) {

+

+          //

+          // Read the HeaderType to determine if this is a multi-function device

+          //

+          IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);

+

+          //

+          // Call the callback function for the device that was found

+          //

+          Callback(

+            IoDev, 

+            MinBus, MaxBus,

+            MinDevice, MaxDevice,

+            MinFunc, MaxFunc,

+            Bus,

+            Device,

+            Func,

+            Context

+            );

+

+          //

+          // If this is not a multi-function device, we can leave the loop 

+          // to deal with the next device.

+          //

+          if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {

+            break;

+          }

+        }  

+      }

+    }

+  }

+}

+

+VOID

+CheckForRom (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+{

+  EFI_STATUS                                 Status;

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64                                     Address;

+  PCI_TYPE00                                 PciHeader;

+  PCI_TYPE01                                 *PciBridgeHeader;

+  UINT32                                     Register;

+  UINT32                                     RomBar;

+  UINT32                                     RomBarSize;

+  EFI_PHYSICAL_ADDRESS                       RomBuffer;

+  UINT32                                     MaxRomSize;

+  EFI_PCI_EXPANSION_ROM_HEADER               EfiRomHeader;

+  PCI_DATA_STRUCTURE                         Pcir;

+  EFI_PCI_OPTION_ROM_DESCRIPTOR              *TempPciOptionRomDescriptors;

+  BOOLEAN                                    LastImage;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

+

+  //

+  // Save the contents of the PCI Configuration Header

+  //

+  IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);

+

+  if (IS_PCI_BRIDGE(&PciHeader)) {

+

+    PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);

+

+    //

+    // See if the PCI-PCI Bridge has its secondary interface enabled.

+    //

+    if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {

+

+      //

+      // Disable the Prefetchable Memory Window

+      //

+      Register = 0x00000000;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);

+      Register = 0xffffffff;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);

+

+      //

+      // Program Memory Window to the PCI Root Bridge Memory Window

+      //

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);

+

+      //

+      // Enable the Memory decode for the PCI-PCI Bridge

+      //

+      IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+      Register |= 0x02;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+

+      //

+      // Recurse on the Secondary Bus Number

+      //

+      ScanPciBus(

+        IoDev,

+        PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, 

+        0, PCI_MAX_DEVICE, 

+        0, PCI_MAX_FUNC, 

+        CheckForRom, Context

+        );

+    }

+  } else {

+

+    //

+    // Check if an Option ROM Register is present and save the Option ROM Window Register

+    //

+    RomBar = 0xffffffff;

+    IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+    IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+

+    RomBarSize = (~(RomBar & 0xfffff800)) + 1;

+

+    //

+    // Make sure the size of the ROM is between 0 and 16 MB

+    //

+    if (RomBarSize > 0 && RomBarSize <= 0x01000000) {

+

+      //

+      // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window

+      //

+      RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;

+      RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;

+      if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {

+        MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;

+        RomBar = RomBar + 1;

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+        IoDev->Pci.Read  (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+        RomBar = RomBar - 1;

+

+        //

+        // Enable the Memory decode for the PCI Device

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+        Register |= 0x02;

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+

+        //

+        // Follow the chain of images to determine the size of the Option ROM present

+        // Keep going until the last image is found by looking at the Indicator field

+        // or the size of an image is 0, or the size of all the images is bigger than the

+        // size of the window programmed into the PPB.

+        //

+        RomBarSize = 0;

+        do {

+

+          LastImage = TRUE;

+

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

+          IoDev->Mem.Read (

+            IoDev, 

+            EfiPciWidthUint8, 

+            RomBar + RomBarSize, 

+            sizeof(EfiRomHeader),

+            &EfiRomHeader

+            );

+

+          Pcir.ImageLength = 0;

+

+          if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&

+              EfiRomHeader.PcirOffset != 0 &&

+              (EfiRomHeader.PcirOffset & 3) == 0 &&

+              RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {

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

+            IoDev->Mem.Read (

+              IoDev, 

+              EfiPciWidthUint8, 

+              RomBar + RomBarSize + EfiRomHeader.PcirOffset, 

+              sizeof(Pcir),

+              &Pcir

+              );

+

+            if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {

+              break;

+            }

+            if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {

+              break;

+            }

+            if ((Pcir.Indicator & 0x80) == 0x00) {

+              LastImage = FALSE;

+            }

+

+            RomBarSize += Pcir.ImageLength * 512;

+          }

+        } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);

+

+        if (RomBarSize > 0) {

+

+          //

+          // Allocate a memory buffer for the Option ROM contents.

+          //

+          Status = gBS->AllocatePages(

+                          AllocateAnyPages,

+                          EfiBootServicesData,

+                          EFI_SIZE_TO_PAGES(RomBarSize),

+                          &RomBuffer

+                          );

+

+          if (!EFI_ERROR (Status)) {

+

+            //

+            // Copy the contents of the Option ROM to the memory buffer

+            //

+            IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);

+

+            Status = gBS->AllocatePool(

+                            EfiBootServicesData,

+                            ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),

+                            (VOID*)&TempPciOptionRomDescriptors

+                            );

+            if (mPciOptionRomTable.PciOptionRomCount > 0) {

+              CopyMem(

+                TempPciOptionRomDescriptors, 

+                mPciOptionRomTable.PciOptionRomDescriptors, 

+                (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)

+                );

+

+              gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);

+            }

+

+            mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; 

+

+            TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);

+

+            TempPciOptionRomDescriptors->RomAddress              = RomBuffer;

+            TempPciOptionRomDescriptors->MemoryType              = EfiBootServicesData;

+            TempPciOptionRomDescriptors->RomLength               = RomBarSize;

+            TempPciOptionRomDescriptors->Seg                     = (UINT32)IoDev->SegmentNumber;

+            TempPciOptionRomDescriptors->Bus                     = (UINT8)Bus;

+            TempPciOptionRomDescriptors->Dev                     = (UINT8)Device;

+            TempPciOptionRomDescriptors->Func                    = (UINT8)Func;

+            TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;

+            TempPciOptionRomDescriptors->DontLoadEfiRom          = FALSE;

+

+            mPciOptionRomTable.PciOptionRomCount++;

+          }

+        }

+

+        //

+        // Disable the Memory decode for the PCI-PCI Bridge

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+        Register &= (~0x02);

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+      }

+    }

+  }

+

+  //

+  // Restore the PCI Configuration Header 

+  //

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);

+}

+

+VOID

+SaveCommandRegister (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64  Address;

+  UINTN   Index;

+  UINT16  Command;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

+

+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

+

+  IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);

+

+  //

+  // Clear the memory enable bit

+  //

+  Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));

+

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);

+}

+

+VOID

+RestoreCommandRegister (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64                                     Address;

+  UINTN                                      Index;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

+

+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

+

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);

+}

+

+EFI_STATUS

+ScanPciRootBridgeForRoms(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev

+  )

+  

+{

+  EFI_STATUS                                 Status;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR          *Descriptors; 

+  UINT16                                     MinBus;

+  UINT16                                     MaxBus;

+  UINT64                                     RootWindowBase;

+  UINT64                                     RootWindowLimit;

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  Context;

+

+  if (mPciOptionRomTableInstalled == FALSE) {

+    gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);

+    mPciOptionRomTableInstalled = TRUE;

+  }

+

+  Status = IoDev->Configuration(IoDev, (VOID **)&Descriptors);

+  if (EFI_ERROR (Status) || Descriptors == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  MinBus = 0xffff;

+  MaxBus = 0xffff;

+  RootWindowBase  = 0;

+  RootWindowLimit = 0;

+  while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {

+    //

+    // Find bus range

+    //

+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {

+      MinBus = (UINT16)Descriptors->AddrRangeMin;

+      MaxBus = (UINT16)Descriptors->AddrRangeMax;

+    }

+    //

+    // Find memory descriptors that are not prefetchable

+    //

+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {

+      //

+      // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices

+      //

+      if (Descriptors->AddrRangeMax < 0x100000000ULL) {

+        //

+        // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB

+        //

+        if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {

+          RootWindowBase  = Descriptors->AddrRangeMin;

+          RootWindowLimit = Descriptors->AddrRangeMax;

+        }

+      }

+    }

+    Descriptors ++;

+  }

+

+  //

+  // Make sure a bus range was found

+  //

+  if (MinBus == 0xffff || MaxBus == 0xffff) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Make sure a non-prefetchable memory region was found

+  //

+  if (RootWindowBase == 0 && RootWindowLimit == 0) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Round the Base and Limit values to 1 MB boudaries

+  //

+  RootWindowBase  = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;

+  RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;

+

+  //

+  // Make sure that the size of the rounded window is greater than zero

+  //

+  if (RootWindowLimit <= RootWindowBase) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Allocate buffer to save the Command register from all the PCI devices

+  //

+  Context.CommandRegisterBuffer = NULL;

+  Status = gBS->AllocatePool(

+                  EfiBootServicesData,

+                  sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),

+                  (VOID **)&Context.CommandRegisterBuffer

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Context.PpbMemoryWindow   = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);

+

+  //

+  // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MaxBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    SaveCommandRegister, &Context

+    );

+

+  //

+  // Recursively scan all the busses for PCI Option ROMs

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MinBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    CheckForRom, &Context

+    );

+

+  //

+  // Restore the Command register in all the PCI devices

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MaxBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    RestoreCommandRegister, &Context

+    );

+

+  //

+  // Free the buffer used to save all the Command register values

+  //

+  gBS->FreePool(Context.CommandRegisterBuffer);

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c
new file mode 100644
index 0000000..97857c2
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/Ipf/PcatIo.c
@@ -0,0 +1,459 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+    PcatPciRootBridgeIo.c

+    

+Abstract:

+

+    EFI PC AT PCI Root Bridge Io Protocol

+

+Revision History

+

+--*/

+

+#include "PcatPciRootBridge.h"

+#include <IndustryStandard/Pci.h>

+#include "SalProc.h"

+

+#include EFI_GUID_DEFINITION (SalSystemTable)

+

+//

+// Might be good to put this in an include file, but people may start

+//  using it! They should always access the EFI abstraction that is

+//  contained in this file. Just a little information hiding.

+//

+#define PORT_TO_MEM(_Port) ( ((_Port) & 0xffffffffffff0000) | (((_Port) & 0xfffc) << 10) | ((_Port) & 0x0fff) )

+                                                                           

+//                                                                  

+// Macro's with casts make this much easier to use and read.

+//

+#define PORT_TO_MEM8(_Port)     (*(UINT8  *)(PORT_TO_MEM(_Port)))

+#define PORT_TO_MEM16(_Port)    (*(UINT16 *)(PORT_TO_MEM(_Port)))

+#define PORT_TO_MEM32(_Port)    (*(UINT32 *)(PORT_TO_MEM(_Port)))

+

+#define EFI_PCI_ADDRESS_IA64(_seg, _bus,_dev,_func,_reg) \

+    ( (UINT64) ( (((UINTN)_seg) << 24) + (((UINTN)_bus) << 16) + (((UINTN)_dev) << 11) + (((UINTN)_func) << 8) + ((UINTN)_reg)) )

+

+//

+// Local variables for performing SAL Proc calls

+//

+PLABEL         mSalProcPlabel;

+CALL_SAL_PROC  mGlobalSalProc;

+

+EFI_STATUS

+PcatRootBridgeIoIoRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *UserBuffer

+  )

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

+  UINTN                         InStride;

+  UINTN                         OutStride;

+  UINTN                         AlignMask;

+  UINTN                         Address;

+  PTR                           Buffer;

+  UINT16                        Data16;

+  UINT32                        Data32;

+  

+ 

+  if ( UserBuffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  Address    = (UINTN)  UserAddress;

+  Buffer.buf = (UINT8 *)UserBuffer;

+

+  if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {

+    return EFI_INVALID_PARAMETER;

+  }

+    

+  if ((UINT32)Width >= EfiPciWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Width & 0x03) == EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AlignMask = (1 << (Width & 0x03)) - 1;

+  if ( Address & AlignMask ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InStride  = 1 << (Width & 0x03);

+  OutStride = InStride;

+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    InStride = 0;

+  }

+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    OutStride = 0;

+  }

+  Width = Width & 0x03;

+

+  Address += PrivateData->PhysicalIoBase;

+

+  //

+  // Loop for each iteration and move the data

+  //

+

+  switch (Width) {

+  case EfiPciWidthUint8:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      *Buffer.ui8 = PORT_TO_MEM8(Address);

+      MEMORY_FENCE();

+    }

+    break;

+

+  case EfiPciWidthUint16:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      if (Buffer.ui & 0x1) {

+        Data16 = PORT_TO_MEM16(Address);

+        *Buffer.ui8     = (UINT8)(Data16 & 0xff);

+        *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff);

+      } else {

+        *Buffer.ui16 = PORT_TO_MEM16(Address);

+      }

+      MEMORY_FENCE();

+    }

+    break;

+

+  case EfiPciWidthUint32:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      if (Buffer.ui & 0x3) {

+        Data32 = PORT_TO_MEM32(Address);

+        *Buffer.ui8     = (UINT8)(Data32 & 0xff);

+        *(Buffer.ui8+1) = (UINT8)((Data32 >> 8) & 0xff);

+        *(Buffer.ui8+2) = (UINT8)((Data32 >> 16) & 0xff);

+        *(Buffer.ui8+3) = (UINT8)((Data32 >> 24) & 0xff);

+      } else {

+        *Buffer.ui32 = PORT_TO_MEM32(Address);

+      }

+      MEMORY_FENCE();

+    }

+    break;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PcatRootBridgeIoIoWrite (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  )

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

+  UINTN                          InStride;

+  UINTN                          OutStride;

+  UINTN                          AlignMask;

+  UINTN                          Address;

+  PTR                            Buffer;

+  UINT16                         Data16;

+  UINT32                         Data32;

+

+  if ( UserBuffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  Address    = (UINTN)  UserAddress;

+  Buffer.buf = (UINT8 *)UserBuffer;

+

+  if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) {

+    return EFI_INVALID_PARAMETER;

+  }

+    

+  if (Width < 0 || Width >= EfiPciWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Width & 0x03) == EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AlignMask = (1 << (Width & 0x03)) - 1;

+  if ( Address & AlignMask ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InStride  = 1 << (Width & 0x03);

+  OutStride = InStride;

+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    InStride = 0;

+  }

+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    OutStride = 0;

+  }

+  Width = Width & 0x03;

+

+  Address += PrivateData->PhysicalIoBase;

+

+  //

+  // Loop for each iteration and move the data

+  //

+

+  switch (Width) {

+  case EfiPciWidthUint8:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      PORT_TO_MEM8(Address) = *Buffer.ui8;

+      MEMORY_FENCE();

+    }

+    break;

+

+  case EfiPciWidthUint16:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      if (Buffer.ui & 0x1) {

+        Data16 = *Buffer.ui8;

+        Data16 = Data16 | (*(Buffer.ui8+1) << 8);

+        PORT_TO_MEM16(Address) = Data16;

+      } else {

+        PORT_TO_MEM16(Address) = *Buffer.ui16;

+      }

+      MEMORY_FENCE();

+    }

+    break;

+  case EfiPciWidthUint32:

+    for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) {

+      MEMORY_FENCE();

+      if (Buffer.ui & 0x3) {

+        Data32 = *Buffer.ui8;

+        Data32 = Data32 | (*(Buffer.ui8+1) << 8);

+        Data32 = Data32 | (*(Buffer.ui8+2) << 16);

+        Data32 = Data32 | (*(Buffer.ui8+3) << 24);

+        PORT_TO_MEM32(Address) = Data32;

+      } else {

+        PORT_TO_MEM32(Address) = *Buffer.ui32;

+      }

+      MEMORY_FENCE();

+    }

+    break;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PcatRootBridgeIoGetIoPortMapping (

+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,

+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping

+  )

+/*++

+

+  Get the IO Port Map from the SAL System Table.

+  

+--*/

+{

+  SAL_SYSTEM_TABLE_ASCENDING_ORDER    *SalSystemTable;

+  SAL_ST_MEMORY_DESCRIPTOR_ENTRY      *SalMemDesc;

+  EFI_STATUS                          Status;

+

+  //

+  // On all Itanium architectures, bit 63 is the I/O bit for performming Memory Mapped I/O operations

+  //

+  *MemoryPortMapping = 0x8000000000000000;

+

+  Status = EfiLibGetSystemConfigurationTable(&gEfiSalSystemTableGuid, &SalSystemTable);

+  if (EFI_ERROR(Status)) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // BugBug: Add code to test checksum on the Sal System Table

+  //

+  if (SalSystemTable->Entry0.Type != 0) {

+    return EFI_UNSUPPORTED;

+  }

+

+  mSalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry; 

+  mSalProcPlabel.GP             = SalSystemTable->Entry0.GlobalDataPointer;

+  mGlobalSalProc                = (CALL_SAL_PROC)&mSalProcPlabel.ProcEntryPoint;

+

+  //

+  // The SalSystemTable pointer includes the Type 0 entry.

+  //  The SalMemDesc is Type 1 so it comes next.

+  //

+  SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1);

+  while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) {

+    if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) {

+      *IoPortMapping = SalMemDesc->PhysicalMemoryAddress;

+      *IoPortMapping |= 0x8000000000000000;

+      return EFI_SUCCESS;

+    }

+    SalMemDesc++;

+  }

+  return EFI_UNSUPPORTED;

+}

+

+EFI_STATUS

+PcatRootBridgeIoPciRW (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     BOOLEAN                                Write,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT UINT8                                  *UserBuffer

+  )

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

+  UINTN                          AlignMask;

+  UINTN                          InStride;

+  UINTN                          OutStride;

+  UINT64                         Address;

+  DEFIO_PCI_ADDR                 *Defio;

+  PTR                            Buffer;

+  UINT32                         Data32;

+  UINT16                         Data16;

+  rArg                           Return;

+

+  if (Width < 0 || Width >= EfiPciWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((Width & 0x03) == EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AlignMask = (1 << (Width & 0x03)) - 1;

+  if ( UserAddress & AlignMask ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  InStride  = 1 << (Width & 0x03);

+  OutStride = InStride;

+  if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    InStride = 0;

+  }

+  if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    OutStride = 0;

+  }

+  Width = Width & 0x03;

+

+  Defio = (DEFIO_PCI_ADDR *)&UserAddress;

+

+  if ((Defio->Function > PCI_MAX_FUNC) || (Defio->Device > PCI_MAX_DEVICE)) {

+    return EFI_UNSUPPORTED;

+  }

+  

+  Buffer.buf = (UINT8 *)UserBuffer;

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  Address = EFI_PCI_ADDRESS_IA64(

+              This->SegmentNumber, 

+              Defio->Bus, 

+              Defio->Device, 

+              Defio->Function, 

+              Defio->Register

+              );

+

+  //

+  // PCI Config access are all 32-bit alligned, but by accessing the

+  //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types

+  //  are possible on PCI.

+  //

+  // SalProc takes care of reading the proper register depending on stride

+  //

+

+  EfiAcquireLock(&PrivateData->PciLock);

+

+  while (Count) {

+

+    if(Write) {

+

+      if (Buffer.ui & 0x3) {

+        Data32  = (*(Buffer.ui8+0) << 0);

+        Data32 |= (*(Buffer.ui8+1) << 8);

+        Data32 |= (*(Buffer.ui8+2) << 16);

+        Data32 |= (*(Buffer.ui8+3) << 24);

+      } else {

+        Data32 = *Buffer.ui32;

+      }

+

+      Return.p0 = -3;

+      Return    = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_WRITE,

+                                 Address, 1 << Width, Data32, 0, 0, 0, 0);

+        

+      if(Return.p0) {

+        EfiReleaseLock(&PrivateData->PciLock);

+        return EFI_UNSUPPORTED;

+      }

+

+    } else {

+

+      Return.p0 = -3;

+      Return    = mGlobalSalProc((UINT64) SAL_PCI_CONFIG_READ,

+                                 Address, 1 << Width, 0, 0, 0, 0, 0);

+

+      if(Return.p0) {

+        EfiReleaseLock(&PrivateData->PciLock);

+        return EFI_UNSUPPORTED;

+      }

+

+      switch (Width) {

+      case EfiPciWidthUint8:

+        *Buffer.ui8 = (UINT8)Return.p1;

+        break;

+      case EfiPciWidthUint16:

+        if (Buffer.ui & 0x1) {

+          Data16 = (UINT16)Return.p1;

+          *(Buffer.ui8 + 0) = Data16 & 0xff;

+          *(Buffer.ui8 + 1) = (Data16 >> 8) & 0xff;

+        } else {

+          *Buffer.ui16 = (UINT16)Return.p1;

+        }

+        break;

+      case EfiPciWidthUint32:

+        if (Buffer.ui & 0x3) {

+          Data32 = (UINT32)Return.p1;

+          *(Buffer.ui8 + 0) = (UINT8)(Data32 & 0xff);

+          *(Buffer.ui8 + 1) = (UINT8)((Data32 >> 8) & 0xff);

+          *(Buffer.ui8 + 2) = (UINT8)((Data32 >> 16) & 0xff);

+          *(Buffer.ui8 + 3) = (UINT8)((Data32 >> 24) & 0xff);

+        } else {

+          *Buffer.ui32 = (UINT32)Return.p1;

+        }

+        break;

+      }

+    }

+

+    Address += InStride;

+    Buffer.buf += OutStride;

+    Count -= 1;

+  }

+  

+  EfiReleaseLock(&PrivateData->PciLock);

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+ScanPciRootBridgeForRoms(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev

+  )

+  

+{

+  return EFI_UNSUPPORTED;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
new file mode 100644
index 0000000..f633533
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
@@ -0,0 +1,1009 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PcatPciRootBridge.c

+    

+Abstract:

+

+    EFI PC-AT PCI Root Bridge Controller

+

+--*/

+

+#include "PcatPciRootBridge.h"

+#include "DeviceIo.h"

+

+EFI_CPU_IO2_PROTOCOL *gCpuIo;

+

+EFI_STATUS

+EFIAPI

+InitializePcatPciRootBridge (

+  IN EFI_HANDLE       ImageHandle,

+  IN EFI_SYSTEM_TABLE *SystemTable

+  )

+/*++

+

+Routine Description:

+  Initializes the PCI Root Bridge Controller

+

+Arguments:

+  ImageHandle -

+  SystemTable -

+    

+Returns:

+    None

+

+--*/

+{

+  EFI_STATUS                     Status;

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

+  UINTN                          PciSegmentIndex;

+  UINTN                          PciRootBridgeIndex;

+  UINTN                          PrimaryBusIndex;

+  UINTN                          NumberOfPciRootBridges;

+  UINTN                          NumberOfPciDevices;

+  UINTN                          Device;

+  UINTN                          Function;

+  UINT16                         VendorId;

+  PCI_TYPE01                     PciConfigurationHeader;

+  UINT64                         Address;

+  UINT64                         Value;

+  UINT64                         Base;

+  UINT64                         Limit;

+

+  //

+  // Initialize gCpuIo now since the chipset init code requires it.

+  //

+  Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&gCpuIo);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Initialize variables required to search all PCI segments for PCI devices

+  //

+  PciSegmentIndex        = 0;

+  PciRootBridgeIndex     = 0;

+  NumberOfPciRootBridges = 0;

+  PrimaryBusIndex        = 0;

+

+  while (PciSegmentIndex <= PCI_MAX_SEGMENT) {

+

+    PrivateData = NULL;

+    Status = gBS->AllocatePool(

+                    EfiBootServicesData,

+                    sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),

+                    (VOID **)&PrivateData

+                    );

+    if (EFI_ERROR (Status)) {

+      goto Done;

+    }

+

+    ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));

+

+    //

+    // Initialize the signature of the private data structure

+    //

+    PrivateData->Signature  = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;

+    PrivateData->Handle     = NULL;

+    PrivateData->DevicePath = NULL;

+    InitializeListHead (&PrivateData->MapInfo);

+

+    //

+    // Initialize the PCI root bridge number and the bus range for that root bridge

+    //

+    PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;

+    PrivateData->PrimaryBus       = (UINT32)PrimaryBusIndex;

+    PrivateData->SubordinateBus   = (UINT32)PrimaryBusIndex;

+

+    PrivateData->IoBase      = 0xffffffff;

+    PrivateData->MemBase     = 0xffffffff;

+    PrivateData->Mem32Base   = 0xffffffffffffffffULL;

+    PrivateData->Pmem32Base  = 0xffffffffffffffffULL;

+    PrivateData->Mem64Base   = 0xffffffffffffffffULL;

+    PrivateData->Pmem64Base  = 0xffffffffffffffffULL;

+

+    //

+    // The default mechanism for performing PCI Configuration cycles is to 

+    // use the I/O ports at 0xCF8 and 0xCFC.  This is only used for IA-32.

+    // IPF uses SAL calls to perform PCI COnfiguration cycles

+    //

+    PrivateData->PciAddress  = 0xCF8;

+    PrivateData->PciData     = 0xCFC;

+

+    //

+    // Get the physical I/O base for performing PCI I/O cycles

+    // For IA-32, this is always 0, because IA-32 has IN and OUT instructions

+    // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles

+    //

+    Status = PcatRootBridgeIoGetIoPortMapping (

+               &PrivateData->PhysicalIoBase, 

+               &PrivateData->PhysicalMemoryBase

+               );

+    if (EFI_ERROR (Status)) {

+      goto Done;

+    }

+

+    //

+    // Get PCI Express Base Address

+    //

+    PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);

+    if (PrivateData->PciExpressBaseAddress != 0) {

+      DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));

+    }

+

+    //

+    // Create a lock for performing PCI Configuration cycles

+    //

+    EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);

+

+    //

+    // Initialize the attributes for this PCI root bridge

+    //

+    PrivateData->Attributes  = 0;

+

+    //

+    // Build the EFI Device Path Protocol instance for this PCI Root Bridge

+    //

+    Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE));

+    if (EFI_ERROR (Status)) {

+      goto Done;

+    }

+

+    //

+    // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge

+    //

+    Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);

+    if (EFI_ERROR (Status)) {

+      goto Done;

+    }

+    

+    //

+    // Scan all the PCI devices on the primary bus of the PCI root bridge

+    //

+    for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {

+    

+      for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {

+

+        //

+        // Compute the PCI configuration address of the PCI device to probe

+        //

+        Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);

+

+        //

+        // Read the Vendor ID from the PCI Configuration Header

+        //

+        Status = PrivateData->Io.Pci.Read (

+                                       &PrivateData->Io, 

+                                       EfiPciWidthUint16, 

+                                       Address, 

+                                       sizeof (VendorId) / sizeof (UINT16), 

+                                       &VendorId

+                                       );

+        if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {

+          //

+          // If the PCI Configuration Read fails, or a PCI device does not exist, then 

+          // skip this entire PCI device

+          //

+          break;

+        }

+        if (VendorId == 0xffff) {

+          //

+          // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.

+          //

+          continue;

+        }

+

+        //

+        // Read the entire PCI Configuration Header

+        //

+        Status = PrivateData->Io.Pci.Read (

+                                       &PrivateData->Io, 

+                                       EfiPciWidthUint16, 

+                                       Address, 

+                                       sizeof (PciConfigurationHeader) / sizeof (UINT16), 

+                                       &PciConfigurationHeader

+                                       );

+        if (EFI_ERROR (Status)) {

+          //

+          // If the entire PCI Configuration Header can not be read, then skip this entire PCI device

+          //

+          break;

+        }

+

+

+        //

+        // Increment the number of PCI device found on the primary bus of the PCI root bridge

+        //

+        NumberOfPciDevices++;

+

+        //

+        // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header

+        //

+        if (PciConfigurationHeader.Hdr.Command & 0x20) {

+          PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;

+        }

+

+        //

+        // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number

+        //

+        if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {

+          //

+          // Get the Bus range that the PPB is decoding

+          //

+          if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {

+            //

+            // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's

+            // current subordinate bus number, then update the PCI root bridge's subordinate bus number 

+            //

+            PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;

+          }

+

+          //

+          // Get the I/O range that the PPB is decoding

+          //

+          Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;

+          Base  = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;

+          Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;

+          if (Value == 0x01) {

+            Base  |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);

+            Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);

+          }

+          if (Base < Limit) {

+            if (PrivateData->IoBase > Base) {

+              PrivateData->IoBase = Base;

+            }

+            if (PrivateData->IoLimit < Limit) {

+              PrivateData->IoLimit = Limit;

+            }

+          }

+

+          //

+          // Get the Memory range that the PPB is decoding

+          //

+          Base  = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;

+          Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;

+          if (Base < Limit) {

+            if (PrivateData->MemBase > Base) {

+              PrivateData->MemBase = Base;

+            }

+            if (PrivateData->MemLimit < Limit) {

+              PrivateData->MemLimit = Limit;

+            }

+            if (PrivateData->Mem32Base > Base) {

+              PrivateData->Mem32Base = Base;

+            }

+            if (PrivateData->Mem32Limit < Limit) {

+              PrivateData->Mem32Limit = Limit;

+            }

+          }

+

+          //

+          // Get the Prefetchable Memory range that the PPB is decoding

+          //

+          Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;

+          Base  = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;

+          Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;

+          if (Value == 0x01) {

+            Base  |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);

+            Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);

+          }

+          if (Base < Limit) {

+            if (PrivateData->MemBase > Base) {

+              PrivateData->MemBase = Base;

+            }

+            if (PrivateData->MemLimit < Limit) {

+              PrivateData->MemLimit = Limit;

+            }

+            if (Value == 0x00) {

+              if (PrivateData->Pmem32Base > Base) {

+                PrivateData->Pmem32Base = Base;

+              }

+              if (PrivateData->Pmem32Limit < Limit) {

+                PrivateData->Pmem32Limit = Limit;

+              }

+            }

+            if (Value == 0x01) {

+              if (PrivateData->Pmem64Base > Base) {

+                PrivateData->Pmem64Base = Base;

+              }

+              if (PrivateData->Pmem64Limit < Limit) {

+                PrivateData->Pmem64Limit = Limit;

+              }

+            }

+          }

+

+          //

+          // Look at the PPB Configuration for legacy decoding attributes

+          //

+          if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;

+          }

+          if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;

+          }

+

+        } else {

+          //

+          // Parse the BARs of the PCI device to determine what I/O Ranges,

+          // Memory Ranges, and Prefetchable Memory Ranges the device is decoding

+          //

+          if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {

+            Status = PcatPciRootBridgeParseBars (

+                       PrivateData, 

+                       PciConfigurationHeader.Hdr.Command,

+                       PrimaryBusIndex, 

+                       Device, 

+                       Function

+                       );

+          }

+

+          //

+          // See if the PCI device is an IDE controller

+          //

+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&

+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {

+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;

+            }

+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;

+            }

+            if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;

+            }

+          }

+

+          //

+          // See if the PCI device is a legacy VGA controller

+          //

+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&

+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x01    ) {

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;

+          }

+

+          //

+          // See if the PCI device is a standard VGA controller

+          //

+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&

+              PciConfigurationHeader.Hdr.ClassCode[1] == 0x00    ) {

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;

+            PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;

+          }

+

+          //

+          // See if the PCI Device is a PCI - ISA or PCI - EISA 

+          // or ISA_POSITIVIE_DECODE Bridge device

+          //

+          if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {

+            if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||

+                PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || 

+                PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;

+              PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;

+

+              if (PrivateData->MemBase > 0xa0000) {

+                PrivateData->MemBase = 0xa0000;

+              }

+              if (PrivateData->MemLimit < 0xbffff) {

+               PrivateData->MemLimit = 0xbffff;

+             }

+            }

+          }

+        }

+

+        //

+        // If this device is not a multi function device, then skip the rest of this PCI device

+        //

+        if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {

+          break;

+        }

+      }

+    }

+

+    //

+    // After scanning all the PCI devices on the PCI root bridge's primary bus, update the 

+    // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate

+    // bus number + 1.

+    //

+    PrimaryBusIndex = PrivateData->SubordinateBus + 1;

+

+    //

+    // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge

+    // exists.

+    //

+    if (NumberOfPciDevices > 0) {

+

+      //

+      // Adjust the I/O range used for bounds checking for the legacy decoding attributed

+      //

+      if (PrivateData->Attributes & 0x7f) {

+        PrivateData->IoBase = 0;

+        if (PrivateData->IoLimit < 0xffff) {

+          PrivateData->IoLimit = 0xffff;

+        }

+      }

+

+      //

+      // Adjust the Memory range used for bounds checking for the legacy decoding attributed

+      //

+      if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {

+        if (PrivateData->MemBase > 0xa0000) {

+          PrivateData->MemBase = 0xa0000;

+        }

+        if (PrivateData->MemLimit < 0xbffff) {

+          PrivateData->MemLimit = 0xbffff;

+        }

+      }

+

+      //

+      // Build ACPI descriptors for the resources on the PCI Root Bridge

+      //

+      Status = ConstructConfiguration(PrivateData);

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Create the handle for this PCI Root Bridge 

+      //

+      Status = gBS->InstallMultipleProtocolInterfaces (

+                     &PrivateData->Handle,              

+                     &gEfiDevicePathProtocolGuid,

+                     PrivateData->DevicePath,

+                     &gEfiPciRootBridgeIoProtocolGuid,

+                     &PrivateData->Io,

+                     NULL

+                     );

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Contruct DeviceIoProtocol

+      //

+      Status = DeviceIoConstructor (

+                 PrivateData->Handle,

+                 &PrivateData->Io,

+                 PrivateData->DevicePath,

+                 (UINT16)PrivateData->PrimaryBus,

+                 (UINT16)PrivateData->SubordinateBus

+                 );

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table

+      //

+      Status = ScanPciRootBridgeForRoms(&PrivateData->Io);

+

+      //

+      // Increment the index for the next PCI Root Bridge

+      //

+      PciRootBridgeIndex++;

+

+    } else {

+

+      //

+      // If no PCI Root Bridges were found on the current PCI segment, then exit

+      //

+      if (NumberOfPciRootBridges == 0) {

+        Status = EFI_SUCCESS;

+        goto Done;

+      }

+

+    }

+

+    //

+    // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then

+    // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0

+    // Otherwise, the search is continued on the next PCI Root Bridge

+    //

+    if (PrimaryBusIndex > PCI_MAX_BUS) {

+      PciSegmentIndex++;

+      NumberOfPciRootBridges = 0;

+      PrimaryBusIndex = 0;

+    } else {

+      NumberOfPciRootBridges++;

+    }

+

+  }

+

+  return EFI_SUCCESS;

+

+Done:

+  //

+  // Clean up memory allocated for the PCI Root Bridge that was searched but not created.

+  //

+  if (PrivateData) {

+    if (PrivateData->DevicePath) {

+      gBS->FreePool(PrivateData->DevicePath);

+    }

+    gBS->FreePool (PrivateData);

+  }

+

+  //

+  // If no PCI Root Bridges were discovered, then return the error condition from scanning the

+  // first PCI Root Bridge

+  //

+  if (PciRootBridgeIndex == 0) {

+    return Status;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS 

+ConstructConfiguration(

+  IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+ 

+{

+  EFI_STATUS                         Status;

+  UINT8                              NumConfig;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Configuration;

+  EFI_ACPI_END_TAG_DESCRIPTOR        *ConfigurationEnd;

+

+  NumConfig = 0;

+  PrivateData->Configuration = NULL;

+

+  if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {

+    NumConfig++;

+  }

+  if (PrivateData->IoLimit >= PrivateData->IoBase) {

+    NumConfig++;

+  }

+  if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {

+    NumConfig++;

+  }

+  if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {

+    NumConfig++;

+  }

+  if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {

+    NumConfig++;

+  }

+  if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {

+    NumConfig++;

+  }

+

+  if ( NumConfig == 0 ) {

+

+    //

+    // If there is no resource request

+    //

+    Status = gBS->AllocatePool (

+                    EfiBootServicesData, 

+                    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),

+                    (VOID **)&PrivateData->Configuration

+                    );

+    if (EFI_ERROR (Status )) {

+      return Status;

+    }

+

+    Configuration = PrivateData->Configuration;

+    

+    ZeroMem (

+      Configuration, 

+      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) 

+      );

+    

+    Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration++;

+

+    ConfigurationEnd       = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);

+    ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;

+    ConfigurationEnd->Checksum = 0;

+  }

+

+  //

+  // If there is at least one type of resource request,

+  // allocate a acpi resource node 

+  //

+  Status = gBS->AllocatePool (

+                  EfiBootServicesData, 

+                  sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),

+                  (VOID **)&PrivateData->Configuration

+                  );

+  if (EFI_ERROR (Status )) {

+    return Status;

+  }

+  

+  Configuration = PrivateData->Configuration;

+

+  ZeroMem (

+    Configuration, 

+    sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)

+    );

+

+  if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {

+    Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_BUS;

+    Configuration->SpecificFlag = 0; 

+    Configuration->AddrRangeMin = PrivateData->PrimaryBus;

+    Configuration->AddrRangeMax = PrivateData->SubordinateBus;

+    Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  }

+  //

+  // Deal with io aperture

+  //

+  if (PrivateData->IoLimit >= PrivateData->IoBase) {

+    Configuration->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType      = ACPI_ADDRESS_SPACE_TYPE_IO;

+    Configuration->SpecificFlag = 1; //non ISA range

+    Configuration->AddrRangeMin = PrivateData->IoBase;

+    Configuration->AddrRangeMax = PrivateData->IoLimit;

+    Configuration->AddrLen      = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  }

+

+  //

+  // Deal with mem32 aperture

+  //

+  if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {

+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;

+    Configuration->SpecificFlag         = 0; //Nonprefechable

+    Configuration->AddrSpaceGranularity = 32; //32 bit

+    Configuration->AddrRangeMin         = PrivateData->Mem32Base;

+    Configuration->AddrRangeMax         = PrivateData->Mem32Limit;

+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  } 

+

+  //

+  // Deal with Pmem32 aperture

+  //

+  if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {

+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;

+    Configuration->SpecificFlag         = 0x6; //prefechable

+    Configuration->AddrSpaceGranularity = 32; //32 bit

+    Configuration->AddrRangeMin         = PrivateData->Pmem32Base;

+    Configuration->AddrRangeMax         = PrivateData->Pmem32Limit;

+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  }

+

+  //

+  // Deal with mem64 aperture

+  //

+  if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {

+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;

+    Configuration->SpecificFlag         = 0; //nonprefechable

+    Configuration->AddrSpaceGranularity = 64; //32 bit

+    Configuration->AddrRangeMin         = PrivateData->Mem64Base;

+    Configuration->AddrRangeMax         = PrivateData->Mem64Limit;

+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  }

+

+  //

+  // Deal with Pmem64 aperture

+  //

+  if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {

+    Configuration->Desc                 = ACPI_ADDRESS_SPACE_DESCRIPTOR;

+    Configuration->Len                  = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);

+    Configuration->ResType              = ACPI_ADDRESS_SPACE_TYPE_MEM;

+    Configuration->SpecificFlag         = 0x06; //prefechable

+    Configuration->AddrSpaceGranularity = 64; //32 bit

+    Configuration->AddrRangeMin         = PrivateData->Pmem64Base;

+    Configuration->AddrRangeMax         = PrivateData->Pmem64Limit;

+    Configuration->AddrLen              = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;

+    Configuration++;

+  }

+

+  //

+  // put the checksum

+  //

+  ConfigurationEnd           = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);

+  ConfigurationEnd->Desc     = ACPI_END_TAG_DESCRIPTOR;

+  ConfigurationEnd->Checksum = 0;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS 

+PcatPciRootBridgeBarExisted (

+  IN  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,

+  IN  UINT64                         Address,

+  OUT UINT32                         *OriginalValue,

+  OUT UINT32                         *Value

+  ) 

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS  Status;

+  UINT32      AllOnes;

+  EFI_TPL     OldTpl;

+

+  //

+  // Preserve the original value

+  //

+  Status = PrivateData->Io.Pci.Read (

+                                 &PrivateData->Io, 

+                                 EfiPciWidthUint32, 

+                                 Address, 

+                                 1, 

+                                 OriginalValue

+                                 );

+

+  //

+  // Raise TPL to high level to disable timer interrupt while the BAR is probed

+  //

+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);

+

+  AllOnes = 0xffffffff;

+

+  Status = PrivateData->Io.Pci.Write (

+                                 &PrivateData->Io, 

+                                 EfiPciWidthUint32, 

+                                 Address, 

+                                 1, 

+                                 &AllOnes

+                                 );

+  Status = PrivateData->Io.Pci.Read (

+                                 &PrivateData->Io, 

+                                 EfiPciWidthUint32, 

+                                 Address, 

+                                 1, 

+                                 Value

+                                 );

+

+  //

+  //Write back the original value

+  //

+  Status = PrivateData->Io.Pci.Write (

+                                 &PrivateData->Io, 

+                                 EfiPciWidthUint32, 

+                                 Address, 

+                                 1, 

+                                 OriginalValue

+                                 );

+

+  //

+  // Restore TPL to its original level

+  //

+  gBS->RestoreTPL (OldTpl);

+

+  if ( *Value == 0 ) {

+    return EFI_DEVICE_ERROR;

+  }

+  return Status;

+}

+

+EFI_STATUS

+PcatPciRootBridgeParseBars (

+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,

+  IN UINT16                         Command,

+  IN UINTN                          Bus,

+  IN UINTN                          Device,

+  IN UINTN                          Function

+  )

+/*++

+

+Routine Description:

+

+Arguments:

+

+Returns:

+

+  None

+

+--*/

+{

+  EFI_STATUS  Status;

+  UINT64      Address;

+  UINT32      OriginalValue;

+  UINT32      Value;

+  UINT32      OriginalUpperValue;

+  UINT32      UpperValue;

+  UINT64      Mask;

+  UINTN       Offset;

+  UINT64      Base;

+  UINT64      Length;

+  UINT64      Limit;

+

+  for (Offset = 0x10; Offset < 0x28; Offset += 4) {

+    Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);

+    Status = PcatPciRootBridgeBarExisted (

+               PrivateData,

+               Address,

+               &OriginalValue,

+               &Value

+               );

+

+    if (!EFI_ERROR (Status )) {

+      if ( Value & 0x01 ) { 

+        if (Command & 0x0001) {

+          //

+          //Device I/Os

+          //

+          Mask = 0xfffffffc;

+          Base = OriginalValue & Mask;

+          Length = ((~(Value & Mask)) & Mask) + 0x04;

+          if (!(Value & 0xFFFF0000)){

+            Length &= 0x0000FFFF;

+          }

+          Limit = Base + Length - 1;

+

+          if (Base < Limit) {

+            if (PrivateData->IoBase > Base) {

+              PrivateData->IoBase = (UINT32)Base;

+            }

+            if (PrivateData->IoLimit < Limit) {

+              PrivateData->IoLimit = (UINT32)Limit;

+            }

+          }

+        }

+   

+      } else {

+

+        if (Command & 0x0002) {

+

+          Mask = 0xfffffff0;

+          Base = OriginalValue & Mask;

+          Length = Value & Mask;

+ 

+          if ((Value & 0x07) != 0x04) {

+            Length = ((~Length) + 1) & 0xffffffff;

+          } else {

+            Offset += 4; 

+            Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);

+

+            Status = PcatPciRootBridgeBarExisted (

+                       PrivateData,

+                       Address,

+                       &OriginalUpperValue,

+                       &UpperValue

+                       );

+

+            Base   = Base | LShiftU64((UINT64)OriginalUpperValue,32);

+            Length = Length | LShiftU64((UINT64)UpperValue,32);

+            Length = (~Length) + 1;

+          }

+

+          Limit = Base + Length - 1;

+

+          if (Base < Limit) {

+            if (PrivateData->MemBase > Base) {

+              PrivateData->MemBase = Base;

+            }

+            if (PrivateData->MemLimit < Limit) {

+              PrivateData->MemLimit = Limit;

+            }

+

+            switch (Value &0x07) {

+            case 0x00: ////memory space; anywhere in 32 bit address space

+              if (Value & 0x08) {

+                if (PrivateData->Pmem32Base > Base) {

+                  PrivateData->Pmem32Base = Base;

+                }

+                if (PrivateData->Pmem32Limit < Limit) {

+                  PrivateData->Pmem32Limit = Limit;

+                }

+              } else {

+                if (PrivateData->Mem32Base > Base) {

+                  PrivateData->Mem32Base = Base;

+                }

+                if (PrivateData->Mem32Limit < Limit) {

+                  PrivateData->Mem32Limit = Limit;

+                }

+              }

+              break;

+            case 0x04: //memory space; anywhere in 64 bit address space

+              if (Value & 0x08) {

+                if (PrivateData->Pmem64Base > Base) {

+                  PrivateData->Pmem64Base = Base;

+                }

+                if (PrivateData->Pmem64Limit < Limit) {

+                  PrivateData->Pmem64Limit = Limit;

+                }

+              } else {

+                if (PrivateData->Mem64Base > Base) {

+                  PrivateData->Mem64Base = Base;

+                }

+                if (PrivateData->Mem64Limit < Limit) {

+                  PrivateData->Mem64Limit = Limit;

+                }

+              }

+              break;

+            }

+          }

+        }

+      }

+    }

+  }

+  return EFI_SUCCESS;

+}

+

+UINT64

+GetPciExpressBaseAddressForRootBridge (

+  IN UINTN    HostBridgeNumber,

+  IN UINTN    RootBridgeNumber

+  )

+/*++

+

+Routine Description:

+  This routine is to get PciExpress Base Address for this RootBridge

+

+Arguments:

+  HostBridgeNumber - The number of HostBridge

+  RootBridgeNumber - The number of RootBridge

+    

+Returns:

+  UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge

+

+--*/

+{

+  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;

+  UINTN                                    BufferSize;

+  UINT32                                   Index;

+  UINT32                                   Number;

+  EFI_PEI_HOB_POINTERS                     GuidHob;

+

+  //

+  // Get PciExpressAddressInfo Hob

+  //

+  PciExpressBaseAddressInfo = NULL;

+  BufferSize                = 0;

+  GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);

+  if (GuidHob.Raw != NULL) {

+    PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);

+    BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);

+  } else {

+    return 0;

+  }

+

+  //

+  // Search the PciExpress Base Address in the Hob for current RootBridge

+  //

+  Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));

+  for (Index = 0; Index < Number; Index++) {

+    if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&

+        (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {

+      return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;

+    }

+  }

+

+  //

+  // Do not find the PciExpress Base Address in the Hob

+  //

+  return 0;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h
new file mode 100644
index 0000000..0450fcf
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.h
@@ -0,0 +1,244 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+  PcatPciRootBridge.h

+

+Abstract:

+

+  The driver for the host to pci bridge (root bridge).

+

+--*/

+

+#ifndef _PCAT_PCI_ROOT_BRIDGE_H_

+#define _PCAT_PCI_ROOT_BRIDGE_H_

+

+#include <PiDxe.h>

+#include <Protocol/PciRootBridgeIo.h>

+#include <Protocol/DeviceIo.h>

+#include <Protocol/CpuIo2.h>

+

+#include <Library/UefiLib.h>

+#include <Library/BaseLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/HobLib.h>

+

+#include <Guid/PciOptionRomTable.h>

+#include <Guid/HobList.h>

+#include <Guid/PciExpressBaseAddress.h>

+

+#include <IndustryStandard/Acpi.h>

+#include <IndustryStandard/Pci.h>

+

+#define PCI_MAX_SEGMENT   0

+//

+// Driver Instance Data Prototypes

+//

+#define PCAT_PCI_ROOT_BRIDGE_SIGNATURE  SIGNATURE_32('p', 'c', 'r', 'b')

+

+typedef struct {

+  UINT32                            Signature;

+  EFI_HANDLE                        Handle;

+                                    

+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   Io;

+  EFI_CPU_IO2_PROTOCOL              *CpuIo;

+

+  UINT32                            RootBridgeNumber;

+  UINT32                            PrimaryBus;

+  UINT32                            SubordinateBus;

+                                     

+  UINT64                            MemBase;     // Offsets host to bus memory addr.

+  UINT64                            MemLimit;    // Max allowable memory access

+                                    

+  UINT64                            IoBase;      // Offsets host to bus io addr.

+  UINT64                            IoLimit;     // Max allowable io access

+                                    

+  UINT64                            PciAddress;

+  UINT64                            PciData;

+                                    

+  UINT64                            PhysicalMemoryBase;

+  UINT64                            PhysicalIoBase;

+                                     

+  EFI_LOCK                          PciLock;

+                                    

+  UINT64                            Attributes;

+                                    

+  UINT64                            Mem32Base;

+  UINT64                            Mem32Limit;

+  UINT64                            Pmem32Base;

+  UINT64                            Pmem32Limit;

+  UINT64                            Mem64Base;

+  UINT64                            Mem64Limit;

+  UINT64                            Pmem64Base;

+  UINT64                            Pmem64Limit;

+

+  UINT64                            PciExpressBaseAddress;

+

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;

+

+  LIST_ENTRY                    MapInfo;

+} PCAT_PCI_ROOT_BRIDGE_INSTANCE;

+

+//

+// Driver Instance Data Macros

+//

+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \

+  CR(a, PCAT_PCI_ROOT_BRIDGE_INSTANCE, Io, PCAT_PCI_ROOT_BRIDGE_SIGNATURE)

+

+//

+// Private data types

+//

+typedef union {

+  UINT8   volatile  *buf;

+  UINT8   volatile  *ui8;

+  UINT16  volatile  *ui16;

+  UINT32  volatile  *ui32;

+  UINT64  volatile  *ui64;

+  UINTN   volatile  ui;

+} PTR;

+

+typedef struct {

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation;

+  UINTN                                      NumberOfBytes;

+  UINTN                                      NumberOfPages;

+  EFI_PHYSICAL_ADDRESS                       HostAddress;

+  EFI_PHYSICAL_ADDRESS                       MappedHostAddress;

+} MAP_INFO;

+

+typedef struct {

+  LIST_ENTRY Link;

+  MAP_INFO * Map;  

+} MAP_INFO_INSTANCE;

+

+typedef

+VOID

+(*EFI_PCI_BUS_SCAN_CALLBACK) (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *Context

+  );

+

+typedef struct {

+  UINT16                    *CommandRegisterBuffer;

+  UINT32                    PpbMemoryWindow;     

+} PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT;

+

+typedef struct {

+  UINT8 Register;

+  UINT8 Function;

+  UINT8 Device;

+  UINT8 Bus;

+  UINT8 Reserved[4];

+} DEFIO_PCI_ADDR;

+

+//

+// Driver Protocol Constructor Prototypes

+//

+EFI_STATUS 

+ConstructConfiguration(

+  IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData

+  );

+

+EFI_STATUS

+PcatPciRootBridgeParseBars (

+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,

+  IN UINT16                         Command,

+  IN UINTN                          Bus,

+  IN UINTN                          Device,

+  IN UINTN                          Function

+  );

+

+EFI_STATUS

+ScanPciRootBridgeForRoms(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev

+  );

+

+EFI_STATUS

+PcatRootBridgeDevicePathConstructor (

+  IN EFI_DEVICE_PATH_PROTOCOL  **Protocol,

+  IN UINTN                     RootBridgeNumber,

+  IN BOOLEAN                   IsPciExpress

+  );

+

+EFI_STATUS

+PcatRootBridgeIoConstructor (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *Protocol,

+  IN UINTN                            SegmentNumber

+  );

+

+EFI_STATUS

+PcatRootBridgeIoGetIoPortMapping (

+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,

+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping

+  );

+

+EFI_STATUS

+PcatRootBridgeIoPciRW (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN BOOLEAN                                Write,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  );

+

+UINT64

+GetPciExpressBaseAddressForRootBridge (

+  IN UINTN    HostBridgeNumber,

+  IN UINTN    RootBridgeNumber

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *UserBuffer

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoWrite (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *UserBuffer

+  );

+

+//

+// Driver entry point prototype

+//

+EFI_STATUS

+EFIAPI

+InitializePcatPciRootBridge (

+  IN EFI_HANDLE       ImageHandle,

+  IN EFI_SYSTEM_TABLE *SystemTable

+  );

+

+extern EFI_CPU_IO2_PROTOCOL  *gCpuIo;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c
new file mode 100644
index 0000000..05891ea
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeDevicePath.c
@@ -0,0 +1,93 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+    PcatPciRootBridgeDevicePath.c

+    

+Abstract:

+

+    EFI PCAT PCI Root Bridge Device Path Protocol

+

+Revision History

+

+--*/

+

+#include "PcatPciRootBridge.h"

+

+//

+// Static device path declarations for this driver.

+//

+

+typedef struct {

+  ACPI_HID_DEVICE_PATH              AcpiDevicePath;

+  EFI_DEVICE_PATH_PROTOCOL          EndDevicePath;

+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;

+

+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {

+  {

+    {

+      ACPI_DEVICE_PATH,

+      ACPI_DP,

+      {

+        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),

+        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),

+      }

+    },

+    EISA_PNP_ID(0x0A03),

+    0

+  },

+  {

+    END_DEVICE_PATH_TYPE,

+    END_ENTIRE_DEVICE_PATH_SUBTYPE,

+    {

+      END_DEVICE_PATH_LENGTH,

+      0

+    }

+  }

+};

+

+EFI_STATUS

+PcatRootBridgeDevicePathConstructor (

+  IN EFI_DEVICE_PATH_PROTOCOL  **Protocol,

+  IN UINTN                     RootBridgeNumber,

+  IN BOOLEAN                   IsPciExpress

+  )

+/*++

+

+Routine Description:

+

+    Construct the device path protocol

+

+Arguments:

+

+    Protocol - protocol to initialize

+    

+Returns:

+

+    None

+

+--*/

+{

+  ACPI_HID_DEVICE_PATH  *AcpiDevicePath;

+ 

+  *Protocol = DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(&mEfiPciRootBridgeDevicePath));

+

+  AcpiDevicePath = (ACPI_HID_DEVICE_PATH *)(*Protocol);

+ 

+  AcpiDevicePath->UID = (UINT32)RootBridgeNumber;

+

+  if (IsPciExpress) {

+    AcpiDevicePath->HID = EISA_PNP_ID(0x0A08);

+  }

+

+  return EFI_SUCCESS;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
new file mode 100644
index 0000000..d5d79ae
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridgeIo.c
@@ -0,0 +1,1036 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+    PcatPciRootBridgeIo.c

+    

+Abstract:

+

+    EFI PC AT PCI Root Bridge Io Protocol

+

+Revision History

+

+--*/

+

+#include "PcatPciRootBridge.h"

+

+//

+// Protocol Member Function Prototypes

+//

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPollMem ( 

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT64                                 Address,

+  IN  UINT64                                 Mask,

+  IN  UINT64                                 Value,

+  IN  UINT64                                 Delay,

+  OUT UINT64                                 *Result

+  );

+  

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPollIo ( 

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT64                                 Address,

+  IN  UINT64                                 Mask,

+  IN  UINT64                                 Value,

+  IN  UINT64                                 Delay,

+  OUT UINT64                                 *Result

+  );

+  

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemWrite (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoCopyMem (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 DestAddress,

+  IN UINT64                                 SrcAddress,

+  IN UINTN                                  Count

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPciRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPciWrite (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMap (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,

+  IN     VOID                                       *HostAddress,

+  IN OUT UINTN                                      *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,

+  OUT    VOID                                       **Mapping

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoUnmap (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN VOID                             *Mapping

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoAllocateBuffer (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN  EFI_ALLOCATE_TYPE                Type,

+  IN  EFI_MEMORY_TYPE                  MemoryType,

+  IN  UINTN                            Pages,

+  OUT VOID                             **HostAddress,

+  IN  UINT64                           Attributes

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoFreeBuffer (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN  UINTN                            Pages,

+  OUT VOID                             *HostAddress

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoFlush (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoGetAttributes (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  OUT UINT64                           *Supported,

+  OUT UINT64                           *Attributes

+  );

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoSetAttributes (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN     UINT64                           Attributes,

+  IN OUT UINT64                           *ResourceBase,

+  IN OUT UINT64                           *ResourceLength 

+  ); 

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoConfiguration (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  OUT VOID                             **Resources

+  );

+

+//

+// Private Function Prototypes

+//

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemRW (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINTN                                  Count,

+  IN  BOOLEAN                                InStrideFlag,

+  IN  PTR                                    In,

+  IN  BOOLEAN                                OutStrideFlag,

+  OUT PTR                                    Out

+  );

+

+EFI_STATUS

+PcatRootBridgeIoConstructor (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *Protocol,

+  IN UINTN                            SegmentNumber

+  )

+/*++

+

+Routine Description:

+

+    Contruct the Pci Root Bridge Io protocol

+

+Arguments:

+

+    Protocol - protocol to initialize

+    

+Returns:

+

+    None

+

+--*/

+{

+  Protocol->ParentHandle   = NULL;

+

+  Protocol->PollMem        = PcatRootBridgeIoPollMem;

+  Protocol->PollIo         = PcatRootBridgeIoPollIo;

+

+  Protocol->Mem.Read       = PcatRootBridgeIoMemRead;

+  Protocol->Mem.Write      = PcatRootBridgeIoMemWrite;

+

+  Protocol->Io.Read        = PcatRootBridgeIoIoRead;

+  Protocol->Io.Write       = PcatRootBridgeIoIoWrite;

+

+  Protocol->CopyMem        = PcatRootBridgeIoCopyMem;

+

+  Protocol->Pci.Read       = PcatRootBridgeIoPciRead;

+  Protocol->Pci.Write      = PcatRootBridgeIoPciWrite;

+

+  Protocol->Map            = PcatRootBridgeIoMap;

+  Protocol->Unmap          = PcatRootBridgeIoUnmap;

+

+  Protocol->AllocateBuffer = PcatRootBridgeIoAllocateBuffer;

+  Protocol->FreeBuffer     = PcatRootBridgeIoFreeBuffer;

+

+  Protocol->Flush          = PcatRootBridgeIoFlush;

+

+  Protocol->GetAttributes  = PcatRootBridgeIoGetAttributes;

+  Protocol->SetAttributes  = PcatRootBridgeIoSetAttributes;

+

+  Protocol->Configuration  = PcatRootBridgeIoConfiguration;

+

+  Protocol->SegmentNumber  = (UINT32)SegmentNumber;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPollMem ( 

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT64                                 Address,

+  IN  UINT64                                 Mask,

+  IN  UINT64                                 Value,

+  IN  UINT64                                 Delay,

+  OUT UINT64                                 *Result

+  )

+{

+  EFI_STATUS  Status;

+  UINT64      NumberOfTicks;

+  UINT32      Remainder;

+

+  if (Result == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+

+  if ((UINT32)Width > EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // No matter what, always do a single poll.

+  //

+  Status = This->Mem.Read (This, Width, Address, 1, Result);

+  if ( EFI_ERROR(Status) ) {

+    return Status;

+  }    

+  if ( (*Result & Mask) == Value ) {

+    return EFI_SUCCESS;

+  }

+

+  if (Delay == 0) {

+    return EFI_SUCCESS;

+  } else {

+

+    NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);

+    if ( Remainder !=0 ) {

+      NumberOfTicks += 1;

+    }

+    NumberOfTicks += 1;

+  

+    while ( NumberOfTicks ) {

+

+      gBS->Stall (10);

+

+      Status = This->Mem.Read (This, Width, Address, 1, Result);

+      if ( EFI_ERROR(Status) ) {

+        return Status;

+      }

+    

+      if ( (*Result & Mask) == Value ) {

+        return EFI_SUCCESS;

+      }

+

+      NumberOfTicks -= 1;

+    }

+  }

+  return EFI_TIMEOUT;

+}

+  

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPollIo ( 

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINT64                                 Address,

+  IN  UINT64                                 Mask,

+  IN  UINT64                                 Value,

+  IN  UINT64                                 Delay,

+  OUT UINT64                                 *Result

+  )

+{

+  EFI_STATUS  Status;

+  UINT64      NumberOfTicks;

+  UINT32       Remainder;

+

+  if (Result == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if ((UINT32)Width > EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // No matter what, always do a single poll.

+  //

+  Status = This->Io.Read (This, Width, Address, 1, Result);

+  if ( EFI_ERROR(Status) ) {

+    return Status;

+  }    

+  if ( (*Result & Mask) == Value ) {

+    return EFI_SUCCESS;

+  }

+

+  if (Delay == 0) {

+    return EFI_SUCCESS;

+  } else {

+

+    NumberOfTicks = DivU64x32Remainder (Delay, 100, &Remainder);

+    if ( Remainder !=0 ) {

+      NumberOfTicks += 1;

+    }

+    NumberOfTicks += 1;

+  

+    while ( NumberOfTicks ) {

+

+      gBS->Stall(10);

+    

+      Status = This->Io.Read (This, Width, Address, 1, Result);

+      if ( EFI_ERROR(Status) ) {

+        return Status;

+      }

+    

+      if ( (*Result & Mask) == Value ) {

+        return EFI_SUCCESS;

+      }

+

+      NumberOfTicks -= 1;

+    }

+  }

+  return EFI_TIMEOUT;

+}

+

+BOOLEAN

+PcatRootBridgeMemAddressValid (

+  IN PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData,

+  IN UINT64                         Address

+  )

+{

+  if ((Address >= PrivateData->PciExpressBaseAddress) && (Address < PrivateData->PciExpressBaseAddress + 0x10000000)) {

+    return TRUE;

+  }

+  if ((Address >= PrivateData->MemBase) && (Address < PrivateData->MemLimit)) {

+    return TRUE;

+  }

+

+  return FALSE;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  )

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;

+  UINTN                          AlignMask;

+  PTR                            In;

+  PTR                            Out;

+

+  if ( Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AlignMask = (1 << (Width & 0x03)) - 1;

+  if (Address & AlignMask) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Address += PrivateData->PhysicalMemoryBase;

+

+  In.buf  = Buffer;

+  Out.buf = (VOID *)(UINTN) Address;

+  if ((UINT32)Width <= EfiPciWidthUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);

+  }

+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);

+  }

+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);

+  }

+

+  return EFI_INVALID_PARAMETER;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemWrite (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  )

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

+  UINTN  AlignMask;

+  PTR    In;

+  PTR    Out;

+

+  if ( Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AlignMask = (1 << (Width & 0x03)) - 1;

+  if (Address & AlignMask) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Address += PrivateData->PhysicalMemoryBase;

+

+  In.buf  = (VOID *)(UINTN) Address;

+  Out.buf = Buffer;

+  if ((UINT32)Width <= EfiPciWidthUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);

+  }

+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);

+  }

+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);

+  }

+

+  return EFI_INVALID_PARAMETER;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoCopyMem (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 DestAddress,

+  IN UINT64                                 SrcAddress,

+  IN UINTN                                  Count

+  )

+

+{

+  EFI_STATUS  Status;

+  BOOLEAN     Direction;

+  UINTN       Stride;

+  UINTN       Index;

+  UINT64      Result;

+

+  if ((UINT32)Width > EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }       

+

+  if (DestAddress == SrcAddress) {

+    return EFI_SUCCESS;

+  }

+

+  Stride = (UINTN)1 << Width;

+

+  Direction = TRUE;

+  if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {

+    Direction   = FALSE;

+    SrcAddress  = SrcAddress  + (Count-1) * Stride;

+    DestAddress = DestAddress + (Count-1) * Stride;

+  }

+

+  for (Index = 0;Index < Count;Index++) {

+    Status = PcatRootBridgeIoMemRead (

+               This,

+               Width,

+               SrcAddress,

+               1,

+               &Result

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+    Status = PcatRootBridgeIoMemWrite (

+               This,

+               Width,

+               DestAddress,

+               1,

+               &Result

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+    if (Direction) {

+      SrcAddress  += Stride;

+      DestAddress += Stride;

+    } else {

+      SrcAddress  -= Stride;

+      DestAddress -= Stride;

+    }

+  }

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPciRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  )

+{

+  if (Buffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return PcatRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoPciWrite (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 Address,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *Buffer

+  )

+{

+  if (Buffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  return PcatRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMap (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,

+  IN     VOID                                       *HostAddress,

+  IN OUT UINTN                                      *NumberOfBytes,

+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,

+  OUT    VOID                                       **Mapping

+  )

+

+{

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;

+  MAP_INFO              *MapInfo;

+  MAP_INFO_INSTANCE    *MapInstance;

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

+

+  if ( HostAddress == NULL || NumberOfBytes == NULL || 

+       DeviceAddress == NULL || Mapping == NULL ) {

+    

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Perform a fence operation to make sure all memory operations are flushed

+  //

+  MemoryFence();

+

+  //

+  // Initialize the return values to their defaults

+  //

+  *Mapping = NULL;

+

+  //

+  // Make sure that Operation is valid

+  //

+  if ((UINT32)Operation >= EfiPciOperationMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Most PCAT like chipsets can not handle performing DMA above 4GB.

+  // If any part of the DMA transfer being mapped is above 4GB, then

+  // map the DMA transfer to a buffer below 4GB.

+  //

+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;

+  if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {

+

+    //

+    // Common Buffer operations can not be remapped.  If the common buffer

+    // if above 4GB, then it is not possible to generate a mapping, so return 

+    // an error.

+    //

+    if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {

+      return EFI_UNSUPPORTED;

+    }

+

+    //

+    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is

+    // called later.

+    //

+    Status = gBS->AllocatePool (

+                    EfiBootServicesData, 

+                    sizeof(MAP_INFO), 

+                    (VOID **)&MapInfo

+                    );

+    if (EFI_ERROR (Status)) {

+      *NumberOfBytes = 0;

+      return Status;

+    }

+

+    //

+    // Return a pointer to the MAP_INFO structure in Mapping

+    //

+    *Mapping = MapInfo;

+

+    //

+    // Initialize the MAP_INFO structure

+    //

+    MapInfo->Operation         = Operation;

+    MapInfo->NumberOfBytes     = *NumberOfBytes;

+    MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);

+    MapInfo->HostAddress       = PhysicalAddress;

+    MapInfo->MappedHostAddress = 0x00000000ffffffff;

+

+    //

+    // Allocate a buffer below 4GB to map the transfer to.

+    //

+    Status = gBS->AllocatePages (

+                    AllocateMaxAddress, 

+                    EfiBootServicesData, 

+                    MapInfo->NumberOfPages,

+                    &MapInfo->MappedHostAddress

+                    );

+    if (EFI_ERROR(Status)) {

+      gBS->FreePool (MapInfo);

+      *NumberOfBytes = 0;

+      return Status;

+    }

+

+    //

+    // If this is a read operation from the Bus Master's point of view,

+    // then copy the contents of the real buffer into the mapped buffer

+    // so the Bus Master can read the contents of the real buffer.

+    //

+    if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {

+      CopyMem (

+        (VOID *)(UINTN)MapInfo->MappedHostAddress, 

+        (VOID *)(UINTN)MapInfo->HostAddress,

+        MapInfo->NumberOfBytes

+        );

+    }

+

+

+  Status =gBS->AllocatePool (

+                    EfiBootServicesData, 

+                    sizeof(MAP_INFO_INSTANCE), 

+                    (VOID **)&MapInstance

+                    );                    

+    if (EFI_ERROR(Status)) {

+      gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages);

+      gBS->FreePool (MapInfo);

+      *NumberOfBytes = 0;

+      return Status;

+    }

+

+    MapInstance->Map=MapInfo;

+    PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+    InsertTailList(&PrivateData->MapInfo,&MapInstance->Link);

+    

+  //

+    // The DeviceAddress is the address of the maped buffer below 4GB

+    //

+    *DeviceAddress = MapInfo->MappedHostAddress;

+  } else {

+    //

+    // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress

+    //

+    *DeviceAddress = PhysicalAddress;

+  }

+

+  //

+  // Perform a fence operation to make sure all memory operations are flushed

+  //

+  MemoryFence();

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoUnmap (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN VOID                             *Mapping

+  )

+

+{

+  MAP_INFO    *MapInfo;

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

+  LIST_ENTRY *Link;

+

+  //

+  // Perform a fence operation to make sure all memory operations are flushed

+  //

+  MemoryFence();

+

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+  //

+  // See if the Map() operation associated with this Unmap() required a mapping buffer.

+  // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.

+  //

+  if (Mapping != NULL) {

+    //

+    // Get the MAP_INFO structure from Mapping

+    //

+    MapInfo = (MAP_INFO *)Mapping;

+

+  for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) {

+      if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo)

+        break;

+    }

+

+    if (Link == &PrivateData->MapInfo) {

+      return EFI_INVALID_PARAMETER;

+  }

+

+    RemoveEntryList(Link);

+    ((MAP_INFO_INSTANCE*)Link)->Map = NULL;

+    gBS->FreePool((MAP_INFO_INSTANCE*)Link);

+

+    //

+    // If this is a write operation from the Bus Master's point of view,

+    // then copy the contents of the mapped buffer into the real buffer

+    // so the processor can read the contents of the real buffer.

+    //

+    if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {

+      CopyMem (

+        (VOID *)(UINTN)MapInfo->HostAddress, 

+        (VOID *)(UINTN)MapInfo->MappedHostAddress,

+        MapInfo->NumberOfBytes

+        );

+    }

+

+    //

+    // Free the mapped buffer and the MAP_INFO structure.

+    //

+    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);

+    gBS->FreePool (Mapping);

+  }

+

+  //

+  // Perform a fence operation to make sure all memory operations are flushed

+  //

+  MemoryFence();

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoAllocateBuffer (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN  EFI_ALLOCATE_TYPE                Type,

+  IN  EFI_MEMORY_TYPE                  MemoryType,

+  IN  UINTN                            Pages,

+  OUT VOID                             **HostAddress,

+  IN  UINT64                           Attributes

+  )

+{

+  EFI_STATUS            Status;

+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;

+

+  //

+  // Validate Attributes

+  //

+  if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {

+    return EFI_UNSUPPORTED;

+  }

+

+  //

+  // Check for invalid inputs

+  //

+  if (HostAddress == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData

+  //

+  if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Limit allocations to memory below 4GB

+  //

+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);

+

+  Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  *HostAddress = (VOID *)(UINTN)PhysicalAddress;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoFreeBuffer (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN  UINTN                            Pages,

+  OUT VOID                             *HostAddress

+  )

+

+{

+

+  if( HostAddress == NULL ){

+     return EFI_INVALID_PARAMETER;

+  } 

+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoFlush (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This

+  )

+

+{

+  //

+  // Perform a fence operation to make sure all memory operations are flushed

+  //

+  MemoryFence();

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoGetAttributes (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  OUT UINT64                           *Supported,  OPTIONAL

+  OUT UINT64                           *Attributes

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;

+

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  if (Attributes == NULL && Supported == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Supported is an OPTIONAL parameter.  See if it is NULL

+  //

+  if (Supported) {

+    //

+    // This is a generic driver for a PC-AT class system.  It does not have any

+    // chipset specific knowlegde, so none of the attributes can be set or 

+    // cleared.  Any attempt to set attribute that are already set will succeed, 

+    // and any attempt to set an attribute that is not supported will fail.

+    //

+    *Supported = PrivateData->Attributes;

+  }

+

+  //

+  // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized

+  //

+  

+  if (Attributes) {

+    *Attributes = PrivateData->Attributes;

+  }

+  

+   

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoSetAttributes (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  IN     UINT64                           Attributes,

+  IN OUT UINT64                           *ResourceBase,

+  IN OUT UINT64                           *ResourceLength 

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  //

+  // This is a generic driver for a PC-AT class system.  It does not have any

+  // chipset specific knowlegde, so none of the attributes can be set or 

+  // cleared.  Any attempt to set attribute that are already set will succeed, 

+  // and any attempt to set an attribute that is not supported will fail.

+  //

+  if (Attributes & (~PrivateData->Attributes)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoConfiguration (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,

+  OUT VOID                             **Resources

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE   *PrivateData;

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  *Resources = PrivateData->Configuration;

+

+  return EFI_SUCCESS;

+}

+

+//

+// Internal function

+//

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoMemRW (

+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN  UINTN                                  Count,

+  IN  BOOLEAN                                InStrideFlag,

+  IN  PTR                                    In,

+  IN  BOOLEAN                                OutStrideFlag,

+  OUT PTR                                    Out

+  )

+/*++

+

+Routine Description:

+

+  Private service to provide the memory read/write

+

+Arguments:

+

+  Width of the Memory Access

+  Count of the number of accesses to perform

+

+Returns:

+

+  Status

+

+  EFI_SUCCESS           - Successful transaction

+  EFI_INVALID_PARAMETER - Unsupported width and address combination

+

+--*/

+{

+  UINTN  Stride;

+  UINTN  InStride;

+  UINTN  OutStride;

+

+

+  Width     = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);

+  Stride    = (UINTN)1 << Width;

+  InStride  = InStrideFlag  ? Stride : 0;

+  OutStride = OutStrideFlag ? Stride : 0;

+

+  //

+  // Loop for each iteration and move the data

+  //

+  switch (Width) {

+  case EfiPciWidthUint8:

+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {

+      MemoryFence();

+      *In.ui8 = *Out.ui8;

+      MemoryFence();

+    }

+    break;

+  case EfiPciWidthUint16:

+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {

+      MemoryFence();

+      *In.ui16 = *Out.ui16;

+      MemoryFence();

+    }

+    break;

+  case EfiPciWidthUint32:

+    for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {

+      MemoryFence();

+      *In.ui32 = *Out.ui32;

+      MemoryFence();

+    }

+    break;

+  default:

+    return EFI_INVALID_PARAMETER;

+  }

+

+  return EFI_SUCCESS;

+}

+

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
new file mode 100644
index 0000000..8f7ef1b
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
@@ -0,0 +1,69 @@
+## @file

+# 

+# Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+#

+#  Module Name:

+#

+#  Abstract:

+#

+##

+

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = PcatPciRootBridge

+  FILE_GUID                      = 0F7EC77A-1EE1-400f-A99D-7CBD1FEB181E

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+

+  ENTRY_POINT                    = InitializePcatPciRootBridge

+

+[Packages]

+  MdePkg/MdePkg.dec

+  DuetPkg/DuetPkg.dec

+

+[LibraryClasses]

+  UefiDriverEntryPoint

+  UefiLib

+  MemoryAllocationLib

+  UefiBootServicesTableLib

+  DebugLib

+  BaseMemoryLib

+  DevicePathLib

+  HobLib

+

+[Sources]

+  PcatPciRootBridge.h

+  PcatPciRootBridge.c

+  PcatPciRootBridgeDevicePath.c

+  PcatPciRootBridgeIo.c

+  DeviceIo.h

+  DeviceIo.c

+

+[Sources.ia32]

+  Ia32/PcatIo.c

+  

+[Sources.x64]

+  X64/PcatIo.c

+

+[Sources.ipf]

+  Ipf/PcatIo.c

+

+[Protocols]

+  gEfiPciRootBridgeIoProtocolGuid

+  gEfiDeviceIoProtocolGuid

+  gEfiCpuIo2ProtocolGuid

+

+[Guids]

+  gEfiPciOptionRomTableGuid

+  gEfiPciExpressBaseAddressGuid

+

+[Depex]

+  gEfiCpuIo2ProtocolGuid

diff --git a/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c
new file mode 100644
index 0000000..179df3d
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c
@@ -0,0 +1,738 @@
+/*++

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+    PcatPciRootBridgeIo.c

+    

+Abstract:

+

+    EFI PC AT PCI Root Bridge Io Protocol

+

+Revision History

+

+--*/

+

+#include "PcatPciRootBridge.h"

+

+BOOLEAN                  mPciOptionRomTableInstalled = FALSE;

+EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable          = {0, NULL};

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoRead (

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN     UINT64                                 UserAddress,

+  IN     UINTN                                  Count,

+  IN OUT VOID                                   *UserBuffer

+  )

+{

+  return gCpuIo->Io.Read (

+                      gCpuIo,

+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,

+                      UserAddress,

+                      Count,

+                      UserBuffer

+                      );

+}

+

+EFI_STATUS

+EFIAPI

+PcatRootBridgeIoIoWrite (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  )

+{

+  return gCpuIo->Io.Write (

+                      gCpuIo,

+                      (EFI_CPU_IO_PROTOCOL_WIDTH) Width,

+                      UserAddress,

+                      Count,

+                      UserBuffer

+                      );

+

+}

+

+EFI_STATUS

+PcatRootBridgeIoGetIoPortMapping (

+  OUT EFI_PHYSICAL_ADDRESS  *IoPortMapping,

+  OUT EFI_PHYSICAL_ADDRESS  *MemoryPortMapping

+  )

+/*++

+

+  Get the IO Port Mapping.  For IA-32 it is always 0.

+  

+--*/

+{

+  *IoPortMapping = 0;

+  *MemoryPortMapping = 0;

+

+  return EFI_SUCCESS;

+}

+

+EFI_STATUS

+PcatRootBridgeIoPciRW (

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,

+  IN BOOLEAN                                Write,

+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,

+  IN UINT64                                 UserAddress,

+  IN UINTN                                  Count,

+  IN OUT VOID                               *UserBuffer

+  )

+{

+  PCI_CONFIG_ACCESS_CF8             Pci;

+  PCI_CONFIG_ACCESS_CF8             PciAligned;

+  UINT32                            InStride;

+  UINT32                            OutStride;

+  UINTN                             PciData;

+  UINTN                             PciDataStride;

+  PCAT_PCI_ROOT_BRIDGE_INSTANCE     *PrivateData;

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;

+  UINT64                            PciExpressRegAddr;

+  BOOLEAN                           UsePciExpressAccess;

+

+  if ((UINT32)Width >= EfiPciWidthMaximum) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  if ((Width & 0x03) >= EfiPciWidthUint64) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);

+

+  InStride    = 1 << (Width & 0x03);

+  OutStride   = InStride;

+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {

+    InStride = 0;

+  }

+

+  if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {

+    OutStride = 0;

+  }

+

+  UsePciExpressAccess = FALSE;

+

+  CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));

+

+  if (PciAddress.ExtendedRegister > 0xFF) {

+    //

+    // Check PciExpressBaseAddress

+    //

+    if ((PrivateData->PciExpressBaseAddress == 0) ||

+        (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {

+      return EFI_UNSUPPORTED;

+    } else {

+      UsePciExpressAccess = TRUE;

+    }

+  } else {

+    if (PciAddress.ExtendedRegister != 0) {

+      Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;

+    } else {

+      Pci.Bits.Reg = PciAddress.Register;

+    }

+    //

+    // Note: We can also use PciExpress access here, if wanted.

+    //

+  }

+

+  if (!UsePciExpressAccess) {

+    Pci.Bits.Func     = PciAddress.Function;

+    Pci.Bits.Dev      = PciAddress.Device;

+    Pci.Bits.Bus      = PciAddress.Bus;

+    Pci.Bits.Reserved = 0;

+    Pci.Bits.Enable   = 1;

+

+    //

+    // PCI Config access are all 32-bit alligned, but by accessing the

+    //  CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types

+    //  are possible on PCI.

+    //

+    // To read a byte of PCI config space you load 0xcf8 and 

+    //  read 0xcfc, 0xcfd, 0xcfe, 0xcff

+    //

+    PciDataStride = Pci.Bits.Reg & 0x03;

+

+    while (Count) {

+      PciAligned = Pci;

+      PciAligned.Bits.Reg &= 0xfc;

+      PciData = (UINTN)PrivateData->PciData + PciDataStride;

+      EfiAcquireLock(&PrivateData->PciLock);

+      This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);

+      if (Write) {

+        This->Io.Write (This, Width, PciData, 1, UserBuffer);

+      } else {

+        This->Io.Read (This, Width, PciData, 1, UserBuffer);

+      }

+      EfiReleaseLock(&PrivateData->PciLock);

+      UserBuffer = ((UINT8 *)UserBuffer) + OutStride;

+      PciDataStride = (PciDataStride + InStride) % 4;

+      Pci.Bits.Reg += InStride;

+      Count -= 1;

+    }

+  } else {

+    //

+    // Access PCI-Express space by using memory mapped method.

+    //

+    PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |

+                        (PciAddress.Bus      << 20) |

+                        (PciAddress.Device   << 15) |

+                        (PciAddress.Function << 12);

+    if (PciAddress.ExtendedRegister != 0) {

+      PciExpressRegAddr += PciAddress.ExtendedRegister;

+    } else {

+      PciExpressRegAddr += PciAddress.Register;

+    }

+    while (Count) {

+      if (Write) {

+        This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);

+      } else {

+        This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);

+      }

+

+      UserBuffer = ((UINT8 *) UserBuffer) + OutStride;

+      PciExpressRegAddr += InStride;

+      Count -= 1;

+    }

+  }

+  

+  return EFI_SUCCESS;

+}

+

+VOID

+ScanPciBus(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  EFI_PCI_BUS_SCAN_CALLBACK        Callback,

+  VOID                             *Context

+  )

+  

+{

+  UINT16      Bus;

+  UINT16      Device;

+  UINT16      Func;

+  UINT64      Address;

+  PCI_TYPE00  PciHeader;

+

+  //

+  // Loop through all busses

+  //

+  for (Bus = MinBus; Bus <= MaxBus; Bus++) {

+    //  

+    // Loop 32 devices per bus

+    //

+    for (Device = MinDevice; Device <= MaxDevice; Device++) {

+      //

+      // Loop through 8 functions per device

+      //

+      for (Func = MinFunc; Func <= MaxFunc; Func++) {

+

+        //

+        // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device

+        //

+        Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

+

+        //

+        // Read the VendorID from this PCI Device's Confioguration Header

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);

+    

+        //

+        // If VendorId = 0xffff, there does not exist a device at this 

+        // location. For each device, if there is any function on it, 

+        // there must be 1 function at Function 0. So if Func = 0, there

+        // will be no more functions in the same device, so we can break

+        // loop to deal with the next device.

+        //  

+        if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {

+          break;

+        }

+        

+        if (PciHeader.Hdr.VendorId != 0xffff) {

+

+          //

+          // Read the HeaderType to determine if this is a multi-function device

+          //

+          IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);

+

+          //

+          // Call the callback function for the device that was found

+          //

+          Callback(

+            IoDev, 

+            MinBus, MaxBus,

+            MinDevice, MaxDevice,

+            MinFunc, MaxFunc,

+            Bus,

+            Device,

+            Func,

+            Context

+            );

+

+          //

+          // If this is not a multi-function device, we can leave the loop 

+          // to deal with the next device.

+          //

+          if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {

+            break;

+          }

+        }  

+      }

+    }

+  }

+}

+

+VOID

+CheckForRom (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+{

+  EFI_STATUS                                 Status;

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64                                     Address;

+  PCI_TYPE00                                 PciHeader;

+  PCI_TYPE01                                 *PciBridgeHeader;

+  UINT32                                     Register;

+  UINT32                                     RomBar;

+  UINT32                                     RomBarSize;

+  EFI_PHYSICAL_ADDRESS                       RomBuffer;

+  UINT32                                     MaxRomSize;

+  EFI_PCI_EXPANSION_ROM_HEADER               EfiRomHeader;

+  PCI_DATA_STRUCTURE                         Pcir;

+  EFI_PCI_OPTION_ROM_DESCRIPTOR              *TempPciOptionRomDescriptors;

+  BOOLEAN                                    LastImage;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);

+

+  //

+  // Save the contents of the PCI Configuration Header

+  //

+  IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);

+

+  if (IS_PCI_BRIDGE(&PciHeader)) {

+

+    PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);

+

+    //

+    // See if the PCI-PCI Bridge has its secondary interface enabled.

+    //

+    if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {

+

+      //

+      // Disable the Prefetchable Memory Window

+      //

+      Register = 0x00000000;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);

+      Register = 0xffffffff;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);

+

+      //

+      // Program Memory Window to the PCI Root Bridge Memory Window

+      //

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);

+

+      //

+      // Enable the Memory decode for the PCI-PCI Bridge

+      //

+      IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+      Register |= 0x02;

+      IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+

+      //

+      // Recurse on the Secondary Bus Number

+      //

+      ScanPciBus(

+        IoDev,

+        PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, 

+        0, PCI_MAX_DEVICE, 

+        0, PCI_MAX_FUNC, 

+        CheckForRom, Context

+        );

+    }

+  } else {

+

+    //

+    // Check if an Option ROM Register is present and save the Option ROM Window Register

+    //

+    RomBar = 0xffffffff;

+    IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+    IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+

+    RomBarSize = (~(RomBar & 0xfffff800)) + 1;

+

+    //

+    // Make sure the size of the ROM is between 0 and 16 MB

+    //

+    if (RomBarSize > 0 && RomBarSize <= 0x01000000) {

+

+      //

+      // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window

+      //

+      RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;

+      RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;

+      if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {

+        MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;

+        RomBar = RomBar + 1;

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+        IoDev->Pci.Read  (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);

+        RomBar = RomBar - 1;

+

+        //

+        // Enable the Memory decode for the PCI Device

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+        Register |= 0x02;

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+

+        //

+        // Follow the chain of images to determine the size of the Option ROM present

+        // Keep going until the last image is found by looking at the Indicator field

+        // or the size of an image is 0, or the size of all the images is bigger than the

+        // size of the window programmed into the PPB.

+        //

+        RomBarSize = 0;

+        do {

+

+          LastImage = TRUE;

+

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

+          IoDev->Mem.Read (

+            IoDev, 

+            EfiPciWidthUint8, 

+            RomBar + RomBarSize, 

+            sizeof(EfiRomHeader),

+            &EfiRomHeader

+            );

+

+          Pcir.ImageLength = 0;

+

+          if (EfiRomHeader.Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE &&

+              EfiRomHeader.PcirOffset != 0 &&

+              (EfiRomHeader.PcirOffset & 3) == 0 &&

+              RomBarSize + EfiRomHeader.PcirOffset + sizeof (PCI_DATA_STRUCTURE) <= MaxRomSize) {

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

+            IoDev->Mem.Read (

+              IoDev, 

+              EfiPciWidthUint8, 

+              RomBar + RomBarSize + EfiRomHeader.PcirOffset, 

+              sizeof(Pcir),

+              &Pcir

+              );

+

+            if (Pcir.Signature != PCI_DATA_STRUCTURE_SIGNATURE) {

+              break;

+            }

+            if (RomBarSize + Pcir.ImageLength * 512 > MaxRomSize) {

+              break;

+            }

+            if ((Pcir.Indicator & 0x80) == 0x00) {

+              LastImage = FALSE;

+            }

+

+            RomBarSize += Pcir.ImageLength * 512;

+          }

+        } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);

+

+        if (RomBarSize > 0) {

+

+          //

+          // Allocate a memory buffer for the Option ROM contents.

+          //

+          Status = gBS->AllocatePages(

+                          AllocateAnyPages,

+                          EfiBootServicesData,

+                          EFI_SIZE_TO_PAGES(RomBarSize),

+                          &RomBuffer

+                          );

+

+          if (!EFI_ERROR (Status)) {

+

+            //

+            // Copy the contents of the Option ROM to the memory buffer

+            //

+            IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);

+

+            Status = gBS->AllocatePool(

+                            EfiBootServicesData,

+                            ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),

+                            (VOID **) &TempPciOptionRomDescriptors

+                            );

+            if (mPciOptionRomTable.PciOptionRomCount > 0) {

+              CopyMem(

+                TempPciOptionRomDescriptors, 

+                mPciOptionRomTable.PciOptionRomDescriptors, 

+                (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)

+                );

+

+              gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);

+            }

+

+            mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; 

+

+            TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);

+

+            TempPciOptionRomDescriptors->RomAddress              = RomBuffer;

+            TempPciOptionRomDescriptors->MemoryType              = EfiBootServicesData;

+            TempPciOptionRomDescriptors->RomLength               = RomBarSize;

+            TempPciOptionRomDescriptors->Seg                     = (UINT32)IoDev->SegmentNumber;

+            TempPciOptionRomDescriptors->Bus                     = (UINT8)Bus;

+            TempPciOptionRomDescriptors->Dev                     = (UINT8)Device;

+            TempPciOptionRomDescriptors->Func                    = (UINT8)Func;

+            TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;

+            TempPciOptionRomDescriptors->DontLoadEfiRom          = FALSE;

+

+            mPciOptionRomTable.PciOptionRomCount++;

+          }

+        }

+

+        //

+        // Disable the Memory decode for the PCI-PCI Bridge

+        //

+        IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+        Register &= (~0x02);

+        IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);

+      }

+    }

+  }

+

+  //

+  // Restore the PCI Configuration Header 

+  //

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);

+}

+

+VOID

+SaveCommandRegister (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64  Address;

+  UINTN   Index;

+  UINT16  Command;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

+

+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

+

+  IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);

+

+  //

+  // Clear the memory enable bit

+  //

+  Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));

+

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);

+}

+

+VOID

+RestoreCommandRegister (

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev,

+  UINT16                           MinBus,

+  UINT16                           MaxBus,

+  UINT16                           MinDevice,

+  UINT16                           MaxDevice,

+  UINT16                           MinFunc,

+  UINT16                           MaxFunc,

+  UINT16                           Bus,

+  UINT16                           Device,

+  UINT16                           Func,

+  IN VOID                          *VoidContext

+  )

+

+{

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  *Context;

+  UINT64                                     Address;

+  UINTN                                      Index;

+

+  Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;

+

+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);

+

+  Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;

+

+  IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);

+}

+

+EFI_STATUS

+ScanPciRootBridgeForRoms(

+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *IoDev

+  )

+  

+{

+  EFI_STATUS                                 Status;

+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR          *Descriptors; 

+  UINT16                                     MinBus;

+  UINT16                                     MaxBus;

+  UINT64                                     RootWindowBase;

+  UINT64                                     RootWindowLimit;

+  PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT  Context;

+

+  if (mPciOptionRomTableInstalled == FALSE) {

+    gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);

+    mPciOptionRomTableInstalled = TRUE;

+  }

+

+  Status = IoDev->Configuration(IoDev, (VOID **) &Descriptors);

+  if (EFI_ERROR (Status) || Descriptors == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  MinBus = 0xffff;

+  MaxBus = 0xffff;

+  RootWindowBase  = 0;

+  RootWindowLimit = 0;

+  while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {

+    //

+    // Find bus range

+    //

+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {

+      MinBus = (UINT16)Descriptors->AddrRangeMin;

+      MaxBus = (UINT16)Descriptors->AddrRangeMax;

+    }

+    //

+    // Find memory descriptors that are not prefetchable

+    //

+    if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {

+      //

+      // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices

+      //

+      if (Descriptors->AddrRangeMax < 0x100000000ULL) {

+        //

+        // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB

+        //

+        if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {

+          RootWindowBase  = Descriptors->AddrRangeMin;

+          RootWindowLimit = Descriptors->AddrRangeMax;

+        }

+      }

+    }

+    Descriptors ++;

+  }

+

+  //

+  // Make sure a bus range was found

+  //

+  if (MinBus == 0xffff || MaxBus == 0xffff) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Make sure a non-prefetchable memory region was found

+  //

+  if (RootWindowBase == 0 && RootWindowLimit == 0) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Round the Base and Limit values to 1 MB boudaries

+  //

+  RootWindowBase  = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;

+  RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;

+

+  //

+  // Make sure that the size of the rounded window is greater than zero

+  //

+  if (RootWindowLimit <= RootWindowBase) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Allocate buffer to save the Command register from all the PCI devices

+  //

+  Context.CommandRegisterBuffer = NULL;

+  Status = gBS->AllocatePool(

+                  EfiBootServicesData,

+                  sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),

+                  (VOID **) &Context.CommandRegisterBuffer

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Context.PpbMemoryWindow   = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);

+

+  //

+  // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MaxBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    SaveCommandRegister, &Context

+    );

+

+  //

+  // Recursively scan all the busses for PCI Option ROMs

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MinBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    CheckForRom, &Context

+    );

+

+  //

+  // Restore the Command register in all the PCI devices

+  //

+  ScanPciBus(

+    IoDev,

+    MinBus, MaxBus, 

+    0, PCI_MAX_DEVICE, 

+    0, PCI_MAX_FUNC, 

+    RestoreCommandRegister, &Context

+    );

+

+  //

+  // Free the buffer used to save all the Command register values

+  //

+  gBS->FreePool(Context.CommandRegisterBuffer);

+

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/PostBuild.bat b/uefi/linaro-edk2/DuetPkg/PostBuild.bat
new file mode 100644
index 0000000..bdcafb8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PostBuild.bat
@@ -0,0 +1,69 @@
+@REM ## @file

+@REM #

+@REM #  Currently, Build system does not provide post build mechanism for module 

+@REM #  and platform building, so just use a bat file to do post build commands.

+@REM #  Originally, following post building command is for EfiLoader module.

+@REM #

+@REM #  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>

+@REM #

+@REM #  This program and the accompanying materials

+@REM #  are licensed and made available under the terms and conditions of the BSD License

+@REM #  which accompanies this distribution. The full text of the license may be found at

+@REM #  http://opensource.org/licenses/bsd-license.php

+@REM #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+@REM #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+@REM #

+@REM #

+@REM ##

+

+@set BASETOOLS_DIR=%WORKSPACE_TOOLS_PATH%\Bin\Win32

+@set BOOTSECTOR_BIN_DIR=%WORKSPACE%\DuetPkg\BootSector\bin

+@set PROCESSOR=""

+@call %WORKSPACE%\DuetPkg\GetVariables.bat

+

+@if NOT "%1"=="" @set TARGET_ARCH=%1

+@if "%TARGET_ARCH%"=="IA32" set PROCESSOR=IA32

+@if "%TARGET_ARCH%"=="X64" set PROCESSOR=X64

+@if %PROCESSOR%=="" goto WrongArch

+

+@set BUILD_DIR=%WORKSPACE%\Build\DuetPkg%PROCESSOR%\%TARGET%_%TOOL_CHAIN_TAG%

+

+

+@echo Compressing DUETEFIMainFv.FV ...

+@%BASETOOLS_DIR%\LzmaCompress -e -o %BUILD_DIR%\FV\DUETEFIMAINFV.z %BUILD_DIR%\FV\DUETEFIMAINFV.Fv

+

+@echo Compressing DxeMain.efi ...

+@%BASETOOLS_DIR%\LzmaCompress -e -o %BUILD_DIR%\FV\DxeMain.z %BUILD_DIR%\%PROCESSOR%\DxeCore.efi

+

+@echo Compressing DxeIpl.efi ...

+@%BASETOOLS_DIR%\LzmaCompress -e -o %BUILD_DIR%\FV\DxeIpl.z %BUILD_DIR%\%PROCESSOR%\DxeIpl.efi

+

+@echo Generate Loader Image ...

+@if "%PROCESSOR%"=="IA32" goto GENERATE_IMAGE_IA32

+@if "%PROCESSOR%"=="X64" goto GENERATE_IMAGE_X64

+

+:GENERATE_IMAGE_IA32

+@%BASETOOLS_DIR%\EfiLdrImage.exe -o %BUILD_DIR%\FV\Efildr32 %BUILD_DIR%\%PROCESSOR%\EfiLoader.efi %BUILD_DIR%\FV\DxeIpl.z %BUILD_DIR%\FV\DxeMain.z %BUILD_DIR%\FV\DUETEFIMAINFV.z

+@copy /b %BOOTSECTOR_BIN_DIR%\Start.com+%BOOTSECTOR_BIN_DIR%\Efi32.com2+%BUILD_DIR%\FV\Efildr32 %BUILD_DIR%\FV\Efildr

+@copy /b %BOOTSECTOR_BIN_DIR%\Start16.com+%BOOTSECTOR_BIN_DIR%\Efi32.com2+%BUILD_DIR%\FV\Efildr32 %BUILD_DIR%\FV\Efildr16

+@copy /b %BOOTSECTOR_BIN_DIR%\Start32.com+%BOOTSECTOR_BIN_DIR%\Efi32.com2+%BUILD_DIR%\FV\Efildr32 %BUILD_DIR%\FV\Efildr20

+@goto end

+

+:GENERATE_IMAGE_X64

+@%BASETOOLS_DIR%\EfiLdrImage.exe -o %BUILD_DIR%\FV\Efildr64 %BUILD_DIR%\%PROCESSOR%\EfiLoader.efi %BUILD_DIR%\FV\DxeIpl.z %BUILD_DIR%\FV\DxeMain.z %BUILD_DIR%\FV\DUETEFIMAINFV.z

+@copy /b %BOOTSECTOR_BIN_DIR%\Start64.com+%BOOTSECTOR_BIN_DIR%\Efi64.com2+%BUILD_DIR%\FV\Efildr64 %BUILD_DIR%\FV\EfildrPure

+@%BASETOOLS_DIR%\GenPage.exe %BUILD_DIR%\FV\EfildrPure -o %BUILD_DIR%\FV\Efildr

+@copy /b %BOOTSECTOR_BIN_DIR%\St16_64.com+%BOOTSECTOR_BIN_DIR%\Efi64.com2+%BUILD_DIR%\FV\Efildr64 %BUILD_DIR%\FV\Efildr16Pure

+@%BASETOOLS_DIR%\GenPage.exe %BUILD_DIR%\FV\Efildr16Pure -o %BUILD_DIR%\FV\Efildr16

+@copy /b %BOOTSECTOR_BIN_DIR%\St32_64.com+%BOOTSECTOR_BIN_DIR%\Efi64.com2+%BUILD_DIR%\FV\Efildr64 %BUILD_DIR%\FV\Efildr20Pure

+@%BASETOOLS_DIR%\GenPage.exe %BUILD_DIR%\FV\Efildr20Pure -o %BUILD_DIR%\FV\Efildr20

+@goto end

+

+

+:WrongArch

+@echo Error! Wrong architecture.

+@goto Help

+

+:Help

+@echo Usage: "PostBuild [IA32|X64]"

+:end
\ No newline at end of file
diff --git a/uefi/linaro-edk2/DuetPkg/PostBuild.sh b/uefi/linaro-edk2/DuetPkg/PostBuild.sh
new file mode 100755
index 0000000..c77c0f3
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/PostBuild.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+
+## @file
+#
+#  Currently, Build system does not provide post build mechanism for module 
+#  and platform building, so just use a sh file to do post build commands.
+#  Originally, following post building command is for EfiLoader module.
+#
+#  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+if [ -z "$EDK_TOOLS_PATH" ]
+then
+export BASETOOLS_DIR=$WORKSPACE/Conf/BaseToolsSource/Source/C/bin
+else
+export BASETOOLS_DIR=$EDK_TOOLS_PATH/Source/C/bin
+fi
+
+export BOOTSECTOR_BIN_DIR=$WORKSPACE/DuetPkg/BootSector/bin
+export PROCESSOR=""
+if [ \
+     -z "$1" -o \
+     "$1" = "-?" -o \
+     "$1" = "-h" -o \
+     "$1" = "--help" \
+   ]
+then
+	echo Error! Please specific the architecture. 
+	echo Usage: "./PostBuild.sh [IA32|X64] [UNIXGCC|GCC44]"
+fi
+
+case "$1" in
+   IA32)
+     export PROCESSOR=IA32
+     ;;
+   X64)
+     export PROCESSOR=X64
+     ;;
+   *)
+     echo Invalid Architecture string, should be only IA32 or X64
+     return 1
+esac
+
+case "$2" in
+   UNIXGCC)
+     export TOOLTAG=UNIXGCC
+     ;;
+   GCC44)
+     export TOOLTAG=GCC44
+     ;;
+   *)
+     echo Invalid tool tag, should be only UNIXGCC or GCC44
+     return 1
+esac
+
+export BUILD_DIR=$WORKSPACE/Build/DuetPkg$PROCESSOR/DEBUG_$TOOLTAG
+
+
+#
+# Boot sector module could only be built under IA32 tool chain
+#
+
+echo Compressing DUETEFIMainFv.FV ...
+$BASETOOLS_DIR/LzmaCompress -e -o $BUILD_DIR/FV/DUETEFIMAINFV.z $BUILD_DIR/FV/DUETEFIMAINFV.Fv
+
+echo Compressing DxeMain.efi ...
+$BASETOOLS_DIR/LzmaCompress -e -o $BUILD_DIR/FV/DxeMain.z $BUILD_DIR/$PROCESSOR/DxeCore.efi
+
+echo Compressing DxeIpl.efi ...
+$BASETOOLS_DIR/LzmaCompress -e -o $BUILD_DIR/FV/DxeIpl.z $BUILD_DIR/$PROCESSOR/DxeIpl.efi	
+
+echo Generate Loader Image ...
+
+if [ $PROCESSOR = IA32 ]
+then
+        $BASETOOLS_DIR/GenFw --rebase 0x10000 -o $BUILD_DIR/$PROCESSOR/EfiLoader.efi $BUILD_DIR/$PROCESSOR/EfiLoader.efi
+	$BASETOOLS_DIR/EfiLdrImage -o $BUILD_DIR/FV/Efildr32 $BUILD_DIR/$PROCESSOR/EfiLoader.efi $BUILD_DIR/FV/DxeIpl.z $BUILD_DIR/FV/DxeMain.z $BUILD_DIR/FV/DUETEFIMAINFV.z
+	cat $BOOTSECTOR_BIN_DIR/Start.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32   > $BUILD_DIR/FV/Efildr
+	#
+	# It is safe to use "bcat" to cat following binary file, if bcat command is avaiable for your system
+	#
+	#bcat -o $BUILD_DIR/FV/Efildr.bcat $BOOTSECTOR_BIN_DIR/start.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32
+	cat $BOOTSECTOR_BIN_DIR/Start16.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32 > $BUILD_DIR/FV/Efildr16
+	#bcat -o $BUILD_DIR/FV/Efildr16.bcat $BOOTSECTOR_BIN_DIR/start16.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32
+	cat $BOOTSECTOR_BIN_DIR/Start32.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32 > $BUILD_DIR/FV/Efildr20	
+	#bcat -o $BUILD_DIR/FV/Efildr20.bcat $BOOTSECTOR_BIN_DIR/start32.com $BOOTSECTOR_BIN_DIR/efi32.com2 $BUILD_DIR/FV/Efildr32
+	echo Done!
+fi
+
+if [ $PROCESSOR = X64 ]
+then
+         $BASETOOLS_DIR/GenFw --rebase 0x10000 -o $BUILD_DIR/$PROCESSOR/EfiLoader.efi $BUILD_DIR/$PROCESSOR/EfiLoader.efi
+	$BASETOOLS_DIR/EfiLdrImage -o $BUILD_DIR/FV/Efildr64 $BUILD_DIR/$PROCESSOR/EfiLoader.efi $BUILD_DIR/FV/DxeIpl.z $BUILD_DIR/FV/DxeMain.z $BUILD_DIR/FV/DUETEFIMAINFV.z
+	cat $BOOTSECTOR_BIN_DIR/Start64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64 > $BUILD_DIR/FV/EfildrPure
+	#bcat -o $BUILD_DIR/FV/EfildrPure $BOOTSECTOR_BIN_DIR/start64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64 
+	$BASETOOLS_DIR/GenPage $BUILD_DIR/FV/EfildrPure -o $BUILD_DIR/FV/Efildr
+	cat $BOOTSECTOR_BIN_DIR/St16_64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64 > $BUILD_DIR/FV/Efildr16Pure
+	#bcat -o $BUILD_DIR/FV/Efildr16Pure $BOOTSECTOR_BIN_DIR/st16_64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64
+	$BASETOOLS_DIR/GenPage $BUILD_DIR/FV/Efildr16Pure -o $BUILD_DIR/FV/Efildr16
+	cat $BOOTSECTOR_BIN_DIR/St32_64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64 > $BUILD_DIR/FV/Efildr20Pure
+	#bcat -o $BUILD_DIR/FV/Efildr20Pure $BOOTSECTOR_BIN_DIR/st32_64.com $BOOTSECTOR_BIN_DIR/efi64.com2 $BUILD_DIR/FV/Efildr64
+	$BASETOOLS_DIR/GenPage $BUILD_DIR/FV/Efildr20Pure -o $BUILD_DIR/FV/Efildr20
+	
+	echo Done!
+fi
+
+
diff --git a/uefi/linaro-edk2/DuetPkg/ReadMe.txt b/uefi/linaro-edk2/DuetPkg/ReadMe.txt
new file mode 100644
index 0000000..f280679
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/ReadMe.txt
@@ -0,0 +1,89 @@
+Developer's UEFI Emulation (DUET) on Edk2

+

+A. Build DUET image on Windows Platform

+========================================

+1. Tools preparation

+

+To build DUET image, following tools are required:

+

+  1). *Visual Studio 2005*

+      Assume installed at <VS_PATH>, 

+      e.g.: C:\Program Files\Microsoft Visual Studio .NET 2003\.

+  2). WinDDK

+      Assume installed at <WIN_DDK_PATH>, e.g.: C:\WINDDK\3790.1830\.

+      

+2. Build steps

+

+2.1 Build Duet Platform module   

+

+  1). run cmd.exe to open command line window.

+  2). enter workspace root directory such as c:\edk2_tree

+  2). run "edksetup.bat"

+  3). run "build -p DuetPkg\DuetPkg.dsc -a IA32" for IA32 architecture platform or 

+          "build -p DuetPkg\DuetPkg.dsc -a X64" for X64 architecture platform.

+ 

+2.2 Execute post build actions  

+  1). enter <Workspace>\DuetPkg directory.

+  2). run "PostBuild.bat IA32" for IA32 architecture platform or 

+          "PostBuild.bat X64" for X64 architecture platform.

+

+Create bootable disk

+======================

+  

+3. Create boot disk

+  The following steps are same for IA32 architecture platform or X64 architecture platform.

+  

+3.1 Create floppy boot disk

+  1). enter <Workspace>\DuetPkg directory.

+  2). Insert a floppy disk to drive

+  3). run "CreateBootDisk.bat floppy a: FAT12 IA32" if floppy drive is a: disk and Arch to boot is IA32.

+      or

+      run "CreateBootDisk.bat floppy a: FAT12 X64" if floppy drive is a: disk and Arch to boot is X64.

+3.2 Create usb boot disk

+  1). enter <Workspace>\DuetPkg directory.

+  2). Plugin usb disk

+  3). run "CreateBootDisk.bat usb e: FAT16 IA32" if usb drive is e: and FAT format is FAT16 and Arch to boot is IA32.

+      or "CreateBootDisk.bat usb e: FAT16 X64" if usb drive is e: and FAT format is FAT16 and Arch to boot is X64.

+      or "CreateBootDisk.bat usb e: FAT32 IA32" if usb drive is e: and FAT format is FAT32 and Arch to boot is IA32.

+      or "CreateBootDisk.bat usb e: FAT32 X64" if usb drive is e: and FAT format is FAT32 and Arch to boot is X64.

+  4). UnPlug usb disk and plugin it again.

+  5). run "CreateBootDisk.bat usb e: FAT16 IA32 step2" if usb drive is e: and FAT format is FAT16 and Arch to boot is IA32.

+      or "CreateBootDisk.bat usb e: FAT16 X64 step2" if usb drive is e: and FAT format is FAT16 and Arch to boot is X64.

+      or "CreateBootDisk.bat usb e: FAT32 IA32 step2" if usb drive is e: and FAT format is FAT32 and Arch to boot is IA32.

+      or "CreateBootDisk.bat usb e: FAT32 X64 step2" if usb drive is e: and FAT format is FAT32 and Arch to boot is X64.

+          

+B. Build DUET image on Linux Platform

+======================================        

+1. Tools preparation

+

+  To build DUET image, GCC44 is required:

+  1). Base on below link to create GCC44 build environment.

+      http://tianocore.sourceforge.net/wiki/Using_EDK_II_with_Native_GCC

+

+2. Build steps

+

+2.1 Build Duet Platform module   

+

+  1). Open the terminal.

+  2). enter workspace root directory such as /edk2_tree

+  3). run ". edksetup.sh BaseTools"

+  4). run "build -p DuetPkg/DuetPkg.dsc -a IA32 -t GCC44" for IA32 architecture platform or 

+          "build -p DuetPkg/DuetPkg.dsc -a X64 -t GCC44" for X64 architecture platform.

+  

+2.2 Execute post build actions  

+  1). enter /edk2_tree/DuetPkg directory.

+  2). run "./PostBuild.sh IA32 GCC44" for IA32 architecture platform or 

+          "./PostBuild.sh X64 GCC44" for X64 architecture platform.

+

+ NOTE: After post build action, you should check the size of EfiLdr at $WORKSPACE/Build/DuetPkg/DEBUG_GCC44 directory, it must less than 470k.

+       If not, you should manually remove some unnecessary drivers at DuetPkg.fdf file.

+ 

+3. Create bootable disk

+   The following steps are same for IA32 architecture platform or X64 architecture platform.

+   Now only support floopy.

+   

+   3.1 Create floppy boot disk

+	  1). enter /edk2_tree/DuetPkg directory.

+	  2). Insert a floppy disk to drive

+	  3). run "CreateBootDisk.sh" to build floppy drive

+		  such as "./CreateBootDisk.sh floppy /media/floppy0 /dev/fd0 FAT12 IA32"
\ No newline at end of file
diff --git a/uefi/linaro-edk2/DuetPkg/SataControllerDxe/ComponentName.c b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/ComponentName.c
new file mode 100644
index 0000000..57cd3c8
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/ComponentName.c
@@ -0,0 +1,176 @@
+/** @file

+  UEFI Component Name(2) protocol implementation for Sata Controller driver.

+

+  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php.

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "SataController.h"

+

+//

+/// EFI Component Name Protocol

+///

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSataControllerComponentName = {

+  SataControllerComponentNameGetDriverName,

+  SataControllerComponentNameGetControllerName,

+  "eng"

+};

+

+//

+/// EFI Component Name 2 Protocol

+///

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2 = {

+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SataControllerComponentNameGetDriverName,

+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SataControllerComponentNameGetControllerName,

+  "en"

+};

+

+//

+/// Driver Name Strings

+///

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerDriverNameTable[] = {

+  {

+    "eng;en",

+    (CHAR16 *)L"Sata Controller Init Driver"

+  },

+  {

+    NULL,

+    NULL

+  }

+};

+

+///

+/// Controller Name Strings

+///

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSataControllerControllerNameTable[] = {

+  {

+    "eng;en",

+    (CHAR16 *)L"Sata Controller"

+  },

+  {

+    NULL,

+    NULL

+  }

+};

+

+/**

+  Retrieves a Unicode string that is the user readable name of the UEFI Driver.

+

+  @param This           A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+  @param Language       A pointer to a three character ISO 639-2 language identifier.

+                        This is the language of the driver name that that the caller

+                        is requesting, and it must match one of the languages specified

+                        in SupportedLanguages.  The number of languages supported by a

+                        driver is up to the driver writer.

+  @param DriverName     A pointer to the Unicode string to return.  This Unicode string

+                        is the name of the driver specified by This in the language

+                        specified by Language.

+  

+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This

+                                and the language specified by Language was returned

+                                in DriverName.

+  @retval EFI_INVALID_PARAMETER Language is NULL.

+  @retval EFI_INVALID_PARAMETER DriverName is NULL.

+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the

+                                language specified by Language.

+**/

+EFI_STATUS

+EFIAPI

+SataControllerComponentNameGetDriverName (

+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,

+  IN CHAR8                          *Language,

+  OUT CHAR16                        **DriverName

+  )

+{

+  return LookupUnicodeString2 (

+           Language,

+           This->SupportedLanguages,

+           mSataControllerDriverNameTable,

+           DriverName,

+           (BOOLEAN)(This == &gSataControllerComponentName)

+           );

+}

+

+/**

+  Retrieves a Unicode string that is the user readable name of the controller

+  that is being managed by an UEFI Driver.  

+

+  @param This                   A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+  @param ControllerHandle       The handle of a controller that the driver specified by

+                                This is managing.  This handle specifies the controller

+                                whose name is to be returned.

+  @param ChildHandle OPTIONAL   The handle of the child controller to retrieve the name

+                                of.  This is an optional parameter that may be NULL.  It

+                                will be NULL for device drivers.  It will also be NULL

+                                for a bus drivers that wish to retrieve the name of the

+                                bus controller.  It will not be NULL for a bus driver

+                                that wishes to retrieve the name of a child controller.

+  @param Language               A pointer to a three character ISO 639-2 language

+                                identifier.  This is the language of the controller name

+                                that that the caller is requesting, and it must match one

+                                of the languages specified in SupportedLanguages.  The

+                                number of languages supported by a driver is up to the

+                                driver writer.

+  @param ControllerName         A pointer to the Unicode string to return.  This Unicode

+                                string is the name of the controller specified by

+                                ControllerHandle and ChildHandle in the language

+                                specified by Language from the point of view of the

+                                driver specified by This.

+  

+  @retval EFI_SUCCESS           The Unicode string for the user readable name in the

+                                language specified by Language for the driver

+                                specified by This was returned in DriverName.

+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.

+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid

+                                EFI_HANDLE.

+  @retval EFI_INVALID_PARAMETER Language is NULL.

+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

+                                managing the controller specified by

+                                ControllerHandle and ChildHandle.

+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the

+                                language specified by Language.

+**/

+EFI_STATUS

+EFIAPI

+SataControllerComponentNameGetControllerName (

+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,

+  IN EFI_HANDLE                     ControllerHandle,

+  IN EFI_HANDLE                     ChildHandle OPTIONAL,

+  IN CHAR8                          *Language,

+  OUT CHAR16                        **ControllerName

+  )

+{

+  EFI_STATUS    Status;

+

+  //

+  // Make sure this driver is currently managing ControllHandle

+  //

+  Status = EfiTestManagedDevice (

+             ControllerHandle,

+             gSataControllerDriverBinding.DriverBindingHandle,

+             &gEfiPciIoProtocolGuid

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  if (ChildHandle != NULL) {

+    return EFI_UNSUPPORTED;

+  }

+

+  return LookupUnicodeString2 (

+          Language,

+          This->SupportedLanguages,

+          mSataControllerControllerNameTable,

+          ControllerName,

+          (BOOLEAN)(This == &gSataControllerComponentName)

+          );

+}

diff --git a/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.c b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.c
new file mode 100644
index 0000000..1807c88
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.c
@@ -0,0 +1,1007 @@
+/** @file

+  This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.

+

+  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "SataController.h"

+

+///

+/// EFI_DRIVER_BINDING_PROTOCOL instance

+///

+EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding = {

+  SataControllerSupported,

+  SataControllerStart,

+  SataControllerStop,

+  0xa,

+  NULL,

+  NULL

+};

+

+/**

+  Read AHCI Operation register.

+

+  @param PciIo      The PCI IO protocol instance.

+  @param Offset     The operation register offset.

+

+  @return The register content read.

+

+**/

+UINT32

+EFIAPI

+AhciReadReg (

+  IN EFI_PCI_IO_PROTOCOL    *PciIo,

+  IN UINT32                 Offset

+  )

+{

+  UINT32    Data;

+

+  ASSERT (PciIo != NULL);

+  

+  Data = 0;

+

+  PciIo->Mem.Read (

+               PciIo,

+               EfiPciIoWidthUint32,

+               AHCI_BAR_INDEX,

+               (UINT64) Offset,

+               1,

+               &Data

+               );

+

+  return Data;

+}

+

+/**

+  Write AHCI Operation register.

+

+  @param PciIo      The PCI IO protocol instance.

+  @param Offset     The operation register offset.

+  @param Data       The data used to write down.

+

+**/

+VOID

+EFIAPI

+AhciWriteReg (

+  IN EFI_PCI_IO_PROTOCOL    *PciIo,

+  IN UINT32                 Offset,

+  IN UINT32                 Data

+  )

+{

+  ASSERT (PciIo != NULL);

+

+  PciIo->Mem.Write (

+               PciIo,

+               EfiPciIoWidthUint32,

+               AHCI_BAR_INDEX,

+               (UINT64) Offset,

+               1,

+               &Data

+               );

+

+  return;

+}

+

+/**

+  This function is used to calculate the best PIO mode supported by specific IDE device

+

+  @param IdentifyData   The identify data of specific IDE device.

+  @param DisPioMode     Disqualified PIO modes collection.

+  @param SelectedMode   Available PIO modes collection.

+

+  @retval EFI_SUCCESS       Best PIO modes are returned.

+  @retval EFI_UNSUPPORTED   The device doesn't support PIO mode,

+                            or all supported modes have been disqualified.

+**/

+EFI_STATUS

+CalculateBestPioMode (

+  IN EFI_IDENTIFY_DATA  *IdentifyData,

+  IN UINT16             *DisPioMode OPTIONAL,

+  OUT UINT16            *SelectedMode

+  )

+{

+  UINT16    PioMode;

+  UINT16    AdvancedPioMode;

+  UINT16    Temp;

+  UINT16    Index;

+  UINT16    MinimumPioCycleTime;

+

+  Temp = 0xff;

+

+  PioMode = (UINT8) (((ATA5_IDENTIFY_DATA *) (&(IdentifyData->AtaData)))->pio_cycle_timing >> 8);

+

+  //

+  // See whether Identify Data word 64 - 70 are valid

+  //

+  if ((IdentifyData->AtaData.field_validity & 0x02) == 0x02) {

+

+    AdvancedPioMode = IdentifyData->AtaData.advanced_pio_modes;

+    DEBUG ((EFI_D_INFO, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode));

+

+    for (Index = 0; Index < 8; Index++) {

+      if ((AdvancedPioMode & 0x01) != 0) {

+        Temp = Index;

+      }

+

+      AdvancedPioMode >>= 1;

+    }

+

+    //

+    // If Temp is modified, mean the advanced_pio_modes is not zero;

+    // if Temp is not modified, mean there is no advanced PIO mode supported,

+    // the best PIO Mode is the value in pio_cycle_timing.

+    //

+    if (Temp != 0xff) {

+      AdvancedPioMode = (UINT16) (Temp + 3);

+    } else {

+      AdvancedPioMode = PioMode;

+    }

+

+    //

+    // Limit the PIO mode to at most PIO4.

+    //

+    PioMode = (UINT16) MIN (AdvancedPioMode, 4);

+

+    MinimumPioCycleTime = IdentifyData->AtaData.min_pio_cycle_time_with_flow_control;

+

+    if (MinimumPioCycleTime <= 120) {

+      PioMode = (UINT16) MIN (4, PioMode);

+    } else if (MinimumPioCycleTime <= 180) {

+      PioMode = (UINT16) MIN (3, PioMode);

+    } else if (MinimumPioCycleTime <= 240) {

+      PioMode = (UINT16) MIN (2, PioMode);

+    } else {

+      PioMode = 0;

+    }

+

+    //

+    // Degrade the PIO mode if the mode has been disqualified

+    //

+    if (DisPioMode != NULL) {

+      if (*DisPioMode < 2) {

+        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2

+      }

+

+      if (PioMode >= *DisPioMode) {

+        PioMode = (UINT16) (*DisPioMode - 1);

+      }

+    }

+

+    if (PioMode < 2) {

+      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;

+    } else {

+      *SelectedMode = PioMode;  // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;

+    }

+

+  } else {

+    //

+    // Identify Data word 64 - 70 are not valid

+    // Degrade the PIO mode if the mode has been disqualified

+    //

+    if (DisPioMode != NULL) {

+      if (*DisPioMode < 2) {

+        return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2

+      }

+

+      if (PioMode == *DisPioMode) {

+        PioMode--;

+      }

+    }

+

+    if (PioMode < 2) {

+      *SelectedMode = 1;        // ATA_PIO_MODE_BELOW_2;

+    } else {

+      *SelectedMode = 2;        // ATA_PIO_MODE_2;

+    }

+

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  This function is used to calculate the best UDMA mode supported by specific IDE device

+

+  @param IdentifyData   The identify data of specific IDE device.

+  @param DisUDmaMode     Disqualified UDMA modes collection.

+  @param SelectedMode   Available UDMA modes collection.

+

+  @retval EFI_SUCCESS       Best UDMA modes are returned.

+  @retval EFI_UNSUPPORTED   The device doesn't support UDMA mode,

+                            or all supported modes have been disqualified.

+**/

+EFI_STATUS

+CalculateBestUdmaMode (

+  IN EFI_IDENTIFY_DATA  *IdentifyData,

+  IN UINT16             *DisUDmaMode OPTIONAL,

+  OUT UINT16            *SelectedMode

+  )

+{

+  UINT16    TempMode;

+  UINT16    DeviceUDmaMode;

+

+  DeviceUDmaMode = 0;

+

+  //

+  // Check whether the WORD 88 (supported UltraDMA by drive) is valid

+  //

+  if ((IdentifyData->AtaData.field_validity & 0x04) == 0x00) {

+    return EFI_UNSUPPORTED;

+  }

+

+  DeviceUDmaMode = IdentifyData->AtaData.ultra_dma_mode;

+  DEBUG ((EFI_D_INFO, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode));

+  DeviceUDmaMode &= 0x3f;

+  TempMode = 0;                 // initialize it to UDMA-0

+

+  while ((DeviceUDmaMode >>= 1) != 0) {

+    TempMode++;

+  }

+

+  //

+  // Degrade the UDMA mode if the mode has been disqualified

+  //

+  if (DisUDmaMode != NULL) {

+    if (*DisUDmaMode == 0) {

+      *SelectedMode = 0;

+      return EFI_UNSUPPORTED;   // no mode below ATA_UDMA_MODE_0

+    }

+

+    if (TempMode >= *DisUDmaMode) {

+      TempMode = (UINT16) (*DisUDmaMode - 1);

+    }

+  }

+

+  //

+  // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5

+  //

+  *SelectedMode = TempMode;

+

+  return EFI_SUCCESS;

+}

+

+/**

+  The Entry Point of module. It follows the standard UEFI driver model.

+

+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  

+  @param[in] SystemTable    A pointer to the EFI System Table.

+  

+  @retval EFI_SUCCESS   The entry point is executed successfully.

+  @retval other         Some error occurs when executing this entry point.

+

+**/

+EFI_STATUS

+EFIAPI

+InitializeSataControllerDriver (

+  IN EFI_HANDLE         ImageHandle,

+  IN EFI_SYSTEM_TABLE   *SystemTable

+  )

+{

+  EFI_STATUS    Status;

+

+  //

+  // Install driver model protocol(s).

+  //

+  Status = EfiLibInstallDriverBindingComponentName2 (

+             ImageHandle,

+             SystemTable,

+             &gSataControllerDriverBinding,

+             ImageHandle,

+             &gSataControllerComponentName,

+             &gSataControllerComponentName2

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}

+

+/**

+  Supported function of Driver Binding protocol for this driver.

+  Test to see if this driver supports ControllerHandle.

+

+  @param This                   Protocol instance pointer.

+  @param Controller             Handle of device to test.

+  @param RemainingDevicePath    A pointer to the device path.

+                                it should be ignored by device driver.

+

+  @retval EFI_SUCCESS           This driver supports this device.

+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.

+  @retval other                 This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+{

+  EFI_STATUS            Status;

+  EFI_PCI_IO_PROTOCOL   *PciIo;

+  PCI_TYPE00            PciData;

+

+  //

+  // Attempt to open PCI I/O Protocol

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Now further check the PCI header: Base Class (offset 0x0B) and

+  // Sub Class (offset 0x0A). This controller should be an SATA controller

+  //

+  Status = PciIo->Pci.Read (

+                        PciIo,

+                        EfiPciIoWidthUint8,

+                        PCI_CLASSCODE_OFFSET,

+                        sizeof (PciData.Hdr.ClassCode),

+                        PciData.Hdr.ClassCode

+                        );

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {

+    return EFI_SUCCESS;

+  }

+

+  return EFI_UNSUPPORTED;

+}

+

+/**

+  This routine is called right after the .Supported() called and 

+  Start this driver on ControllerHandle.

+

+  @param This                   Protocol instance pointer.

+  @param Controller             Handle of device to bind driver to.

+  @param RemainingDevicePath    A pointer to the device path.

+                                it should be ignored by device driver.

+

+  @retval EFI_SUCCESS           This driver is added to this device.

+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.

+  @retval other                 Some error occurs when binding this driver to this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+{

+  EFI_STATUS                        Status;

+  EFI_PCI_IO_PROTOCOL               *PciIo;

+  PCI_TYPE00                        PciData;

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+  UINT32                            Data32;

+  UINTN                             ChannelDeviceCount;

+

+  DEBUG ((EFI_D_INFO, "SataControllerStart START\n"));

+

+  SataPrivateData = NULL;

+

+  //

+  // Now test and open PCI I/O Protocol

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    DEBUG ((EFI_D_ERROR, "SataControllerStart error return status = %r\n", Status));

+    return Status;

+  }

+

+  //

+  // Allocate Sata Private Data structure

+  //

+  SataPrivateData = AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA));

+  if (SataPrivateData == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Done;

+  }

+

+  //

+  // Initialize Sata Private Data

+  //

+  SataPrivateData->Signature = SATA_CONTROLLER_SIGNATURE;

+  SataPrivateData->PciIo = PciIo;

+  SataPrivateData->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;

+  SataPrivateData->IdeInit.NotifyPhase = IdeInitNotifyPhase;

+  SataPrivateData->IdeInit.SubmitData = IdeInitSubmitData;

+  SataPrivateData->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;

+  SataPrivateData->IdeInit.CalculateMode = IdeInitCalculateMode;

+  SataPrivateData->IdeInit.SetTiming = IdeInitSetTiming;

+  SataPrivateData->IdeInit.EnumAll = SATA_ENUMER_ALL;

+

+  Status = PciIo->Pci.Read (

+                        PciIo,

+                        EfiPciIoWidthUint8,

+                        PCI_CLASSCODE_OFFSET,

+                        sizeof (PciData.Hdr.ClassCode),

+                        PciData.Hdr.ClassCode

+                        );

+  ASSERT_EFI_ERROR (Status);

+

+  if (IS_PCI_IDE (&PciData)) {

+    SataPrivateData->IdeInit.ChannelCount = IDE_MAX_CHANNEL;

+    SataPrivateData->DeviceCount = IDE_MAX_DEVICES;

+  } else if (IS_PCI_SATADPA (&PciData)) {

+    //

+    // Read Host Capability Register(CAP) to get Number of Ports(NPS) and Supports Port Multiplier(SPM)

+    //   NPS is 0's based value indicating the maximum number of ports supported by the HBA silicon.

+    //   A maximum of 32 ports can be supported. A value of '0h', indicating one port, is the minimum requirement.

+    //

+    Data32 = AhciReadReg (PciIo, R_AHCI_CAP);

+    SataPrivateData->IdeInit.ChannelCount = (UINT8) ((Data32 & B_AHCI_CAP_NPS) + 1);

+    SataPrivateData->DeviceCount = AHCI_MAX_DEVICES;

+    if ((Data32 & B_AHCI_CAP_SPM) == B_AHCI_CAP_SPM) {

+      SataPrivateData->DeviceCount = AHCI_MULTI_MAX_DEVICES;

+    }

+  }

+

+  ChannelDeviceCount = (UINTN) (SataPrivateData->IdeInit.ChannelCount) * (UINTN) (SataPrivateData->DeviceCount);

+  SataPrivateData->DisqulifiedModes = AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE)) * ChannelDeviceCount);

+  if (SataPrivateData->DisqulifiedModes == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Done;

+  }

+

+  SataPrivateData->IdentifyData = AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA)) * ChannelDeviceCount);

+  if (SataPrivateData->IdentifyData == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Done;

+  }

+

+  SataPrivateData->IdentifyValid = AllocateZeroPool ((sizeof (BOOLEAN)) * ChannelDeviceCount);

+  if (SataPrivateData->IdentifyValid == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Done;

+  }

+

+  //

+  // Install IDE Controller Init Protocol to this instance

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &Controller,

+                  &gEfiIdeControllerInitProtocolGuid,

+                  &(SataPrivateData->IdeInit),

+                  NULL

+                  );

+

+Done:

+  if (EFI_ERROR (Status)) {

+

+    gBS->CloseProtocol (

+          Controller,

+          &gEfiPciIoProtocolGuid,

+          This->DriverBindingHandle,

+          Controller

+          );

+    if (SataPrivateData != NULL) {

+      if (SataPrivateData->DisqulifiedModes != NULL) {

+        FreePool (SataPrivateData->DisqulifiedModes);

+      }

+      if (SataPrivateData->IdentifyData != NULL) {

+        FreePool (SataPrivateData->IdentifyData);

+      }

+      if (SataPrivateData->IdentifyValid != NULL) {

+        FreePool (SataPrivateData->IdentifyValid);

+      }

+      FreePool (SataPrivateData);

+    }

+  }

+

+  DEBUG ((EFI_D_INFO, "SataControllerStart END status = %r\n", Status));

+

+  return Status;

+}

+

+/**

+  Stop this driver on ControllerHandle.

+

+  @param This               Protocol instance pointer.

+  @param Controller         Handle of device to stop driver on.

+  @param NumberOfChildren   Not used.

+  @param ChildHandleBuffer  Not used.

+

+  @retval EFI_SUCCESS   This driver is removed from this device.

+  @retval other         Some error occurs when removing this driver from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerStop (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN UINTN                          NumberOfChildren,

+  IN EFI_HANDLE                     *ChildHandleBuffer

+  )

+{

+  EFI_STATUS                        Status;

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+

+  //

+  // Open the produced protocol

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiIdeControllerInitProtocolGuid,

+                  (VOID **) &IdeInit,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                  );

+  if (EFI_ERROR (Status)) {

+    return EFI_UNSUPPORTED;

+  }

+

+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit);

+  ASSERT (SataPrivateData != NULL);

+

+  //

+  // Uninstall the IDE Controller Init Protocol from this instance

+  //

+  Status = gBS->UninstallMultipleProtocolInterfaces (

+                  Controller,

+                  &gEfiIdeControllerInitProtocolGuid,

+                  &(SataPrivateData->IdeInit),

+                  NULL

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  if (SataPrivateData != NULL) {

+    if (SataPrivateData->DisqulifiedModes != NULL) {

+      FreePool (SataPrivateData->DisqulifiedModes);

+    }

+    if (SataPrivateData->IdentifyData != NULL) {

+      FreePool (SataPrivateData->IdentifyData);

+    }

+    if (SataPrivateData->IdentifyValid != NULL) {

+      FreePool (SataPrivateData->IdentifyValid);

+    }

+    FreePool (SataPrivateData);

+  }

+

+  //

+  // Close protocols opened by Sata Controller driver

+  //

+  return gBS->CloseProtocol (

+                Controller,

+                &gEfiPciIoProtocolGuid,

+                This->DriverBindingHandle,

+                Controller

+                );

+}

+

+//

+// Interface functions of IDE_CONTROLLER_INIT protocol

+//

+/**

+  Returns the information about the specified IDE channel.

+  

+  This function can be used to obtain information about a particular IDE channel.

+  The driver entity uses this information during the enumeration process. 

+  

+  If Enabled is set to FALSE, the driver entity will not scan the channel. Note 

+  that it will not prevent an operating system driver from scanning the channel.

+  

+  For most of today's controllers, MaxDevices will either be 1 or 2. For SATA 

+  controllers, this value will always be 1. SATA configurations can contain SATA 

+  port multipliers. SATA port multipliers behave like SATA bridges and can support

+  up to 16 devices on the other side. If a SATA port out of the IDE controller 

+  is connected to a port multiplier, MaxDevices will be set to the number of SATA 

+  devices that the port multiplier supports. Because today's port multipliers 

+  support up to fifteen SATA devices, this number can be as large as fifteen. The IDE  

+  bus driver is required to scan for the presence of port multipliers behind an SATA 

+  controller and enumerate up to MaxDevices number of devices behind the port 

+  multiplier.    

+  

+  In this context, the devices behind a port multiplier constitute a channel.  

+  

+  @param[in]  This         The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in]  Channel      Zero-based channel number.

+  @param[out] Enabled      TRUE if this channel is enabled.  Disabled channels 

+                           are not scanned to see if any devices are present.

+  @param[out] MaxDevices   The maximum number of IDE devices that the bus driver

+                           can expect on this channel.  For the ATA/ATAPI 

+                           specification, version 6, this number will either be 

+                           one or two. For Serial ATA (SATA) configurations with a 

+                           port multiplier, this number can be as large as fifteen.

+

+  @retval EFI_SUCCESS             Information was returned without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitGetChannelInfo (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  OUT BOOLEAN                           *Enabled,

+  OUT UINT8                             *MaxDevices

+  )

+{

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);

+  ASSERT (SataPrivateData != NULL);

+

+  if (Channel < This->ChannelCount) {

+    *Enabled = TRUE;

+    *MaxDevices = SataPrivateData->DeviceCount;

+    return EFI_SUCCESS;

+  }

+

+  *Enabled = FALSE;

+  return EFI_INVALID_PARAMETER;

+}

+

+/**

+  The notifications from the driver entity that it is about to enter a certain

+  phase of the IDE channel enumeration process.

+  

+  This function can be used to notify the IDE controller driver to perform 

+  specific actions, including any chipset-specific initialization, so that the 

+  chipset is ready to enter the next phase. Seven notification points are defined 

+  at this time. 

+  

+  More synchronization points may be added as required in the future.  

+

+  @param[in] This      The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Phase     The phase during enumeration.

+  @param[in] Channel   Zero-based channel number.

+

+  @retval EFI_SUCCESS             The notification was accepted without any errors.

+  @retval EFI_UNSUPPORTED         Phase is not supported.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_NOT_READY           This phase cannot be entered at this time; for 

+                                  example, an attempt was made to enter a Phase 

+                                  without having entered one or more previous 

+                                  Phase.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitNotifyPhase (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN EFI_IDE_CONTROLLER_ENUM_PHASE      Phase,

+  IN UINT8                              Channel

+  )

+{

+  return EFI_SUCCESS;

+}

+

+/**

+  Submits the device information to the IDE controller driver.

+

+  This function is used by the driver entity to pass detailed information about 

+  a particular device to the IDE controller driver. The driver entity obtains 

+  this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData

+  is the pointer to the response data buffer. The IdentifyData buffer is owned 

+  by the driver entity, and the IDE controller driver must make a local copy 

+  of the entire buffer or parts of the buffer as needed. The original IdentifyData 

+  buffer pointer may not be valid when

+  

+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or

+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.

+    

+  The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to 

+  compute the optimum mode for the device. These fields are not limited to the 

+  timing information. For example, an implementation of the IDE controller driver 

+  may examine the vendor and type/mode field to match known bad drives.  

+  

+  The driver entity may submit drive information in any order, as long as it 

+  submits information for all the devices belonging to the enumeration group 

+  before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device

+  in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()

+  should be called with IdentifyData set to NULL.  The IDE controller driver may 

+  not have any other mechanism to know whether a device is present or not. Therefore, 

+  setting IdentifyData to NULL does not constitute an error condition. 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a 

+  given (Channel, Device) pair.  

+    

+  @param[in] This           A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel        Zero-based channel number.

+  @param[in] Device         Zero-based device number on the Channel.

+  @param[in] IdentifyData   The device's response to the ATA IDENTIFY_DEVICE command.

+

+  @retval EFI_SUCCESS             The information was accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitSubmitData (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_IDENTIFY_DATA                  *IdentifyData

+  )

+{

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);

+  ASSERT (SataPrivateData != NULL);

+

+  if ((Channel >= This->ChannelCount) || (Device >= SataPrivateData->DeviceCount)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Make a local copy of device's IdentifyData and mark the valid flag

+  //

+  if (IdentifyData != NULL) {

+    CopyMem (

+      &(SataPrivateData->IdentifyData[Channel * Device]),

+      IdentifyData,

+      sizeof (EFI_IDENTIFY_DATA)

+      );

+

+    SataPrivateData->IdentifyValid[Channel * Device] = TRUE;

+  } else {

+    SataPrivateData->IdentifyValid[Channel * Device] = FALSE;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Disqualifies specific modes for an IDE device.

+

+  This function allows the driver entity or other drivers (such as platform 

+  drivers) to reject certain timing modes and request the IDE controller driver

+  to recalculate modes. This function allows the driver entity and the IDE 

+  controller driver to negotiate the timings on a per-device basis. This function 

+  is useful in the case of drives that lie about their capabilities. An example 

+  is when the IDE device fails to accept the timing modes that are calculated 

+  by the IDE controller driver based on the response to the Identify Drive command.

+

+  If the driver entity does not want to limit the ATA timing modes and leave that 

+  decision to the IDE controller driver, it can either not call this function for 

+  the given device or call this function and set the Valid flag to FALSE for all 

+  modes that are listed in EFI_ATA_COLLECTIVE_MODE.

+  

+  The driver entity may disqualify modes for a device in any order and any number 

+  of times.

+  

+  This function can be called multiple times to invalidate multiple modes of the 

+  same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI 

+  specification for more information on PIO modes.  

+  

+  For Serial ATA (SATA) controllers, this member function can be used to disqualify

+  a higher transfer rate mode on a given channel. For example, a platform driver

+  may inform the IDE controller driver to not use second-generation (Gen2) speeds 

+  for a certain SATA drive.

+  

+  @param[in] This       The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel    The zero-based channel number.

+  @param[in] Device     The zero-based device number on the Channel.

+  @param[in] BadModes   The modes that the device does not support and that

+                        should be disqualified.

+

+  @retval EFI_SUCCESS             The modes were accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+  @retval EFI_INVALID_PARAMETER   IdentifyData is NULL.

+                                

+**/

+EFI_STATUS

+EFIAPI

+IdeInitDisqualifyMode (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_ATA_COLLECTIVE_MODE            *BadModes

+  )

+{

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);

+  ASSERT (SataPrivateData != NULL);

+

+  if ((Channel >= This->ChannelCount) || (BadModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Record the disqualified modes per channel per device. From ATA/ATAPI spec,

+  // if a mode is not supported, the modes higher than it is also not supported.

+  //

+  CopyMem (

+    &(SataPrivateData->DisqulifiedModes[Channel * Device]),

+    BadModes,

+    sizeof (EFI_ATA_COLLECTIVE_MODE)

+    );

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Returns the information about the optimum modes for the specified IDE device.

+

+  This function is used by the driver entity to obtain the optimum ATA modes for

+  a specific device.  The IDE controller driver takes into account the following 

+  while calculating the mode:

+    - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()

+    - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()

+

+  The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 

+  for all the devices that belong to an enumeration group before calling 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.  

+  

+  The IDE controller driver will use controller- and possibly platform-specific 

+  algorithms to arrive at SupportedModes.  The IDE controller may base its 

+  decision on user preferences and other considerations as well. This function 

+  may be called multiple times because the driver entity may renegotiate the mode 

+  with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().

+    

+  The driver entity may collect timing information for various devices in any 

+  order. The driver entity is responsible for making sure that all the dependencies

+  are satisfied. For example, the SupportedModes information for device A that 

+  was previously returned may become stale after a call to 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.

+  

+  The buffer SupportedModes is allocated by the callee because the caller does 

+  not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE 

+  is defined in a way that allows for future extensibility and can be of variable 

+  length. This memory pool should be deallocated by the caller when it is no 

+  longer necessary.  

+  

+  The IDE controller driver for a Serial ATA (SATA) controller can use this 

+  member function to force a lower speed (first-generation [Gen1] speeds on a 

+  second-generation [Gen2]-capable hardware).  The IDE controller driver can 

+  also allow the driver entity to stay with the speed that has been negotiated 

+  by the physical layer.

+  

+  @param[in]  This             The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in]  Channel          A zero-based channel number.

+  @param[in]  Device           A zero-based device number on the Channel.

+  @param[out] SupportedModes   The optimum modes for the device.

+

+  @retval EFI_SUCCESS             SupportedModes was returned.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid. 

+  @retval EFI_INVALID_PARAMETER   SupportedModes is NULL.

+  @retval EFI_NOT_READY           Modes cannot be calculated due to a lack of 

+                                  data.  This error may happen if 

+                                  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 

+                                  and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() 

+                                  were not called for at least one drive in the 

+                                  same enumeration group.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitCalculateMode (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  OUT EFI_ATA_COLLECTIVE_MODE           **SupportedModes

+  )

+{

+  EFI_SATA_CONTROLLER_PRIVATE_DATA  *SataPrivateData;

+  EFI_IDENTIFY_DATA                 *IdentifyData;

+  BOOLEAN                           IdentifyValid;

+  EFI_ATA_COLLECTIVE_MODE           *DisqulifiedModes;

+  UINT16                            SelectedMode;

+  EFI_STATUS                        Status;

+

+  SataPrivateData = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);

+  ASSERT (SataPrivateData != NULL);

+

+  if ((Channel >= This->ChannelCount) || (SupportedModes == NULL) || (Device >= SataPrivateData->DeviceCount)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));

+  if (*SupportedModes == NULL) {

+    ASSERT (*SupportedModes != NULL);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  IdentifyData = &(SataPrivateData->IdentifyData[Channel * Device]);

+  IdentifyValid = SataPrivateData->IdentifyValid[Channel * Device];

+  DisqulifiedModes = &(SataPrivateData->DisqulifiedModes[Channel * Device]);

+

+  //

+  // Make sure we've got the valid identify data of the device from SubmitData()

+  //

+  if (!IdentifyValid) {

+    FreePool (*SupportedModes);

+    return EFI_NOT_READY;

+  }

+

+  Status = CalculateBestPioMode (

+            IdentifyData,

+            (DisqulifiedModes->PioMode.Valid ? ((UINT16 *) &(DisqulifiedModes->PioMode.Mode)) : NULL),

+            &SelectedMode

+            );

+  if (!EFI_ERROR (Status)) {

+    (*SupportedModes)->PioMode.Valid = TRUE;

+    (*SupportedModes)->PioMode.Mode = SelectedMode;

+

+  } else {

+    (*SupportedModes)->PioMode.Valid = FALSE;

+  }

+  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes)->PioMode.Mode));

+

+  Status = CalculateBestUdmaMode (

+            IdentifyData,

+            (DisqulifiedModes->UdmaMode.Valid ? ((UINT16 *) &(DisqulifiedModes->UdmaMode.Mode)) : NULL),

+            &SelectedMode

+            );

+

+  if (!EFI_ERROR (Status)) {

+    (*SupportedModes)->UdmaMode.Valid = TRUE;

+    (*SupportedModes)->UdmaMode.Mode  = SelectedMode;

+

+  } else {

+    (*SupportedModes)->UdmaMode.Valid = FALSE;

+  }

+  DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes)->UdmaMode.Mode));

+

+  //

+  // The modes other than PIO and UDMA are not supported

+  //

+  return EFI_SUCCESS;

+}

+

+/**

+  Commands the IDE controller driver to program the IDE controller hardware

+  so that the specified device can operate at the specified mode.

+

+  This function is used by the driver entity to instruct the IDE controller 

+  driver to program the IDE controller hardware to the specified modes. This 

+  function can be called only once for a particular device. For a Serial ATA 

+  (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-

+  specific programming may be required.

+

+  @param[in] This      Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel   Zero-based channel number.

+  @param[in] Device    Zero-based device number on the Channel.

+  @param[in] Modes     The modes to set.

+

+  @retval EFI_SUCCESS             The command was accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+  @retval EFI_NOT_READY           Modes cannot be set at this time due to lack of data.

+  @retval EFI_DEVICE_ERROR        Modes cannot be set due to hardware failure.

+                                  The driver entity should not use this device.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitSetTiming (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_ATA_COLLECTIVE_MODE            *Modes

+  )

+{

+  return EFI_SUCCESS;

+}

diff --git a/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.h b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.h
new file mode 100644
index 0000000..d2a929f
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataController.h
@@ -0,0 +1,542 @@
+/** @file

+  Header file for Sata Controller driver.

+

+  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+  This program and the accompanying materials

+  are licensed and made available under the terms and conditions of the BSD License

+  which accompanies this distribution.  The full text of the license may be found at

+  http://opensource.org/licenses/bsd-license.php

+

+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#ifndef _SATA_CONTROLLER_H_

+#define _SATA_CONTROLLER_H_

+

+#include <Uefi.h>

+#include <Protocol/ComponentName.h>

+#include <Protocol/DriverBinding.h>

+#include <Protocol/PciIo.h>

+#include <Protocol/IdeControllerInit.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <IndustryStandard/Pci.h>

+

+//

+// Global Variables definitions

+//

+extern EFI_DRIVER_BINDING_PROTOCOL  gSataControllerDriverBinding;

+extern EFI_COMPONENT_NAME_PROTOCOL  gSataControllerComponentName;

+extern EFI_COMPONENT_NAME2_PROTOCOL gSataControllerComponentName2;

+

+#define AHCI_BAR_INDEX 0x05

+#define R_AHCI_CAP 0x0

+#define   B_AHCI_CAP_NPS (BIT4 | BIT3 | BIT2 | BIT1 | BIT0) // Number of Ports

+#define   B_AHCI_CAP_SPM BIT17 // Supports Port Multiplier

+

+///

+/// AHCI each channel can have up to 1 device

+///

+#define AHCI_MAX_DEVICES 0x01

+

+///

+/// AHCI each channel can have 15 devices in the presence of a multiplier

+///

+#define AHCI_MULTI_MAX_DEVICES 0x0F

+

+///

+/// IDE supports 2 channel max

+///

+#define IDE_MAX_CHANNEL 0x02

+

+///

+/// IDE supports 2 devices max

+///

+#define IDE_MAX_DEVICES 0x02

+

+#define SATA_ENUMER_ALL FALSE

+

+//

+// Sata Controller driver private data structure

+//

+

+#define SATA_CONTROLLER_SIGNATURE SIGNATURE_32('S','A','T','A')

+

+typedef struct _EFI_SATA_CONTROLLER_PRIVATE_DATA {

+  //

+  // Standard signature used to identify Sata Controller private data

+  //

+  UINT32                            Signature;

+

+  //

+  // Protocol instance of IDE_CONTROLLER_INIT produced by this driver

+  //

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  IdeInit;

+

+  //

+  // Copy of protocol pointers used by this driver

+  //

+  EFI_PCI_IO_PROTOCOL               *PciIo;

+

+  //

+  // The number of devices that are supported by this channel

+  //

+  UINT8                             DeviceCount;

+

+  //

+  // The highest disqulified mode for each attached device,

+  // From ATA/ATAPI spec, if a mode is not supported,

+  // the modes higher than it is also not supported

+  //

+  EFI_ATA_COLLECTIVE_MODE           *DisqulifiedModes;

+

+  //

+  // A copy of EFI_IDENTIFY_DATA data for each attached SATA device and its flag

+  //

+  EFI_IDENTIFY_DATA                 *IdentifyData;

+  BOOLEAN                           *IdentifyValid;

+} EFI_SATA_CONTROLLER_PRIVATE_DATA;

+

+#define SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_SATA_CONTROLLER_PRIVATE_DATA, IdeInit, SATA_CONTROLLER_SIGNATURE)

+

+//

+// Driver binding functions declaration

+//

+/**

+  Supported function of Driver Binding protocol for this driver.

+  Test to see if this driver supports ControllerHandle.

+

+  @param This                   Protocol instance pointer.

+  @param Controller             Handle of device to test.

+  @param RemainingDevicePath    A pointer to the device path. Should be ignored by

+                                device driver.

+

+  @retval EFI_SUCCESS           This driver supports this device.

+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.

+  @retval other                 This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+;

+

+/**

+  This routine is called right after the .Supported() called and 

+  Start this driver on ControllerHandle.

+

+  @param This                   Protocol instance pointer.

+  @param Controller             Handle of device to bind driver to.

+  @param RemainingDevicePath    A pointer to the device path. Should be ignored by

+                                device driver.

+

+  @retval EFI_SUCCESS           This driver is added to this device.

+  @retval EFI_ALREADY_STARTED   This driver is already running on this device.

+  @retval other                 Some error occurs when binding this driver to this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+;

+

+/**

+  Stop this driver on ControllerHandle.

+

+  @param This               Protocol instance pointer.

+  @param Controller         Handle of device to stop driver on.

+  @param NumberOfChildren   Not used.

+  @param ChildHandleBuffer  Not used.

+

+  @retval EFI_SUCCESS   This driver is removed from this device.

+  @retval other         Some error occurs when removing this driver from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+SataControllerStop (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN UINTN                          NumberOfChildren,

+  IN EFI_HANDLE                     *ChildHandleBuffer

+  )

+;

+

+//

+// IDE controller init functions declaration

+//

+/**

+  Returns the information about the specified IDE channel.

+  

+  This function can be used to obtain information about a particular IDE channel.

+  The driver entity uses this information during the enumeration process. 

+  

+  If Enabled is set to FALSE, the driver entity will not scan the channel. Note 

+  that it will not prevent an operating system driver from scanning the channel.

+  

+  For most of today's controllers, MaxDevices will either be 1 or 2. For SATA 

+  controllers, this value will always be 1. SATA configurations can contain SATA 

+  port multipliers. SATA port multipliers behave like SATA bridges and can support

+  up to 16 devices on the other side. If a SATA port out of the IDE controller 

+  is connected to a port multiplier, MaxDevices will be set to the number of SATA 

+  devices that the port multiplier supports. Because today's port multipliers 

+  support up to fifteen SATA devices, this number can be as large as fifteen. The IDE  

+  bus driver is required to scan for the presence of port multipliers behind an SATA 

+  controller and enumerate up to MaxDevices number of devices behind the port 

+  multiplier.    

+  

+  In this context, the devices behind a port multiplier constitute a channel.  

+  

+  @param[in]  This         The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in]  Channel      Zero-based channel number.

+  @param[out] Enabled      TRUE if this channel is enabled.  Disabled channels 

+                           are not scanned to see if any devices are present.

+  @param[out] MaxDevices   The maximum number of IDE devices that the bus driver

+                           can expect on this channel.  For the ATA/ATAPI 

+                           specification, version 6, this number will either be 

+                           one or two. For Serial ATA (SATA) configurations with a 

+                           port multiplier, this number can be as large as fifteen.

+

+  @retval EFI_SUCCESS             Information was returned without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitGetChannelInfo (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  OUT BOOLEAN                           *Enabled,

+  OUT UINT8                             *MaxDevices

+  )

+;

+

+/**

+  The notifications from the driver entity that it is about to enter a certain

+  phase of the IDE channel enumeration process.

+  

+  This function can be used to notify the IDE controller driver to perform 

+  specific actions, including any chipset-specific initialization, so that the 

+  chipset is ready to enter the next phase. Seven notification points are defined 

+  at this time. 

+  

+  More synchronization points may be added as required in the future.  

+

+  @param[in] This      The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Phase     The phase during enumeration.

+  @param[in] Channel   Zero-based channel number.

+

+  @retval EFI_SUCCESS             The notification was accepted without any errors.

+  @retval EFI_UNSUPPORTED         Phase is not supported.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_NOT_READY           This phase cannot be entered at this time; for 

+                                  example, an attempt was made to enter a Phase 

+                                  without having entered one or more previous 

+                                  Phase.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitNotifyPhase (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN EFI_IDE_CONTROLLER_ENUM_PHASE      Phase,

+  IN UINT8                              Channel

+  )

+;

+

+/**

+  Submits the device information to the IDE controller driver.

+

+  This function is used by the driver entity to pass detailed information about 

+  a particular device to the IDE controller driver. The driver entity obtains 

+  this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData

+  is the pointer to the response data buffer. The IdentifyData buffer is owned 

+  by the driver entity, and the IDE controller driver must make a local copy 

+  of the entire buffer or parts of the buffer as needed. The original IdentifyData 

+  buffer pointer may not be valid when

+  

+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or

+    - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.

+    

+  The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to 

+  compute the optimum mode for the device. These fields are not limited to the 

+  timing information. For example, an implementation of the IDE controller driver 

+  may examine the vendor and type/mode field to match known bad drives.  

+  

+  The driver entity may submit drive information in any order, as long as it 

+  submits information for all the devices belonging to the enumeration group 

+  before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device

+  in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()

+  should be called with IdentifyData set to NULL.  The IDE controller driver may 

+  not have any other mechanism to know whether a device is present or not. Therefore, 

+  setting IdentifyData to NULL does not constitute an error condition. 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a 

+  given (Channel, Device) pair.  

+    

+  @param[in] This           A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel        Zero-based channel number.

+  @param[in] Device         Zero-based device number on the Channel.

+  @param[in] IdentifyData   The device's response to the ATA IDENTIFY_DEVICE command.

+

+  @retval EFI_SUCCESS             The information was accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitSubmitData (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_IDENTIFY_DATA                  *IdentifyData

+  )

+;

+

+/**

+  Disqualifies specific modes for an IDE device.

+

+  This function allows the driver entity or other drivers (such as platform 

+  drivers) to reject certain timing modes and request the IDE controller driver

+  to recalculate modes. This function allows the driver entity and the IDE 

+  controller driver to negotiate the timings on a per-device basis. This function 

+  is useful in the case of drives that lie about their capabilities. An example 

+  is when the IDE device fails to accept the timing modes that are calculated 

+  by the IDE controller driver based on the response to the Identify Drive command.

+

+  If the driver entity does not want to limit the ATA timing modes and leave that 

+  decision to the IDE controller driver, it can either not call this function for 

+  the given device or call this function and set the Valid flag to FALSE for all 

+  modes that are listed in EFI_ATA_COLLECTIVE_MODE.

+  

+  The driver entity may disqualify modes for a device in any order and any number 

+  of times.

+  

+  This function can be called multiple times to invalidate multiple modes of the 

+  same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI 

+  specification for more information on PIO modes.  

+  

+  For Serial ATA (SATA) controllers, this member function can be used to disqualify

+  a higher transfer rate mode on a given channel. For example, a platform driver

+  may inform the IDE controller driver to not use second-generation (Gen2) speeds 

+  for a certain SATA drive.

+  

+  @param[in] This       The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel    The zero-based channel number.

+  @param[in] Device     The zero-based device number on the Channel.

+  @param[in] BadModes   The modes that the device does not support and that

+                        should be disqualified.

+

+  @retval EFI_SUCCESS             The modes were accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+  @retval EFI_INVALID_PARAMETER   IdentifyData is NULL.

+                                

+**/

+EFI_STATUS

+EFIAPI

+IdeInitDisqualifyMode (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_ATA_COLLECTIVE_MODE            *BadModes

+  )

+;

+

+/**

+  Returns the information about the optimum modes for the specified IDE device.

+

+  This function is used by the driver entity to obtain the optimum ATA modes for

+  a specific device.  The IDE controller driver takes into account the following 

+  while calculating the mode:

+    - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()

+    - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()

+

+  The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 

+  for all the devices that belong to an enumeration group before calling 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.  

+  

+  The IDE controller driver will use controller- and possibly platform-specific 

+  algorithms to arrive at SupportedModes.  The IDE controller may base its 

+  decision on user preferences and other considerations as well. This function 

+  may be called multiple times because the driver entity may renegotiate the mode 

+  with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().

+    

+  The driver entity may collect timing information for various devices in any 

+  order. The driver entity is responsible for making sure that all the dependencies

+  are satisfied. For example, the SupportedModes information for device A that 

+  was previously returned may become stale after a call to 

+  EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.

+  

+  The buffer SupportedModes is allocated by the callee because the caller does 

+  not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE 

+  is defined in a way that allows for future extensibility and can be of variable 

+  length. This memory pool should be deallocated by the caller when it is no 

+  longer necessary.  

+  

+  The IDE controller driver for a Serial ATA (SATA) controller can use this 

+  member function to force a lower speed (first-generation [Gen1] speeds on a 

+  second-generation [Gen2]-capable hardware).  The IDE controller driver can 

+  also allow the driver entity to stay with the speed that has been negotiated 

+  by the physical layer.

+  

+  @param[in]  This             The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in]  Channel          A zero-based channel number.

+  @param[in]  Device           A zero-based device number on the Channel.

+  @param[out] SupportedModes   The optimum modes for the device.

+

+  @retval EFI_SUCCESS             SupportedModes was returned.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid. 

+  @retval EFI_INVALID_PARAMETER   SupportedModes is NULL.

+  @retval EFI_NOT_READY           Modes cannot be calculated due to a lack of 

+                                  data.  This error may happen if 

+                                  EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() 

+                                  and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData() 

+                                  were not called for at least one drive in the 

+                                  same enumeration group.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitCalculateMode (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  OUT EFI_ATA_COLLECTIVE_MODE           **SupportedModes

+  )

+;

+

+/**

+  Commands the IDE controller driver to program the IDE controller hardware

+  so that the specified device can operate at the specified mode.

+

+  This function is used by the driver entity to instruct the IDE controller 

+  driver to program the IDE controller hardware to the specified modes. This 

+  function can be called only once for a particular device. For a Serial ATA 

+  (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-

+  specific programming may be required.

+

+  @param[in] This      Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.

+  @param[in] Channel   Zero-based channel number.

+  @param[in] Device    Zero-based device number on the Channel.

+  @param[in] Modes     The modes to set.

+

+  @retval EFI_SUCCESS             The command was accepted without any errors.

+  @retval EFI_INVALID_PARAMETER   Channel is invalid (Channel >= ChannelCount).

+  @retval EFI_INVALID_PARAMETER   Device is invalid.

+  @retval EFI_NOT_READY           Modes cannot be set at this time due to lack of data.

+  @retval EFI_DEVICE_ERROR        Modes cannot be set due to hardware failure.

+                                  The driver entity should not use this device.

+

+**/

+EFI_STATUS

+EFIAPI

+IdeInitSetTiming (

+  IN EFI_IDE_CONTROLLER_INIT_PROTOCOL   *This,

+  IN UINT8                              Channel,

+  IN UINT8                              Device,

+  IN EFI_ATA_COLLECTIVE_MODE            *Modes

+  )

+;

+

+//

+// Forward reference declaration

+//

+/**

+  Retrieves a Unicode string that is the user readable name of the UEFI Driver.

+

+  @param This           A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+  @param Language       A pointer to a three character ISO 639-2 language identifier.

+                        This is the language of the driver name that that the caller

+                        is requesting, and it must match one of the languages specified

+                        in SupportedLanguages.  The number of languages supported by a

+                        driver is up to the driver writer.

+  @param DriverName     A pointer to the Unicode string to return.  This Unicode string

+                        is the name of the driver specified by This in the language

+                        specified by Language.

+

+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This

+                                and the language specified by Language was returned

+                                in DriverName.

+  @retval EFI_INVALID_PARAMETER Language is NULL.

+  @retval EFI_INVALID_PARAMETER DriverName is NULL.

+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the

+                                language specified by Language.

+**/

+EFI_STATUS

+EFIAPI

+SataControllerComponentNameGetDriverName (

+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,

+  IN CHAR8                          *Language,

+  OUT CHAR16                        **DriverName

+  )

+;

+

+/**

+  Retrieves a Unicode string that is the user readable name of the controller

+  that is being managed by an UEFI Driver.

+

+  @param This                   A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+  @param ControllerHandle       The handle of a controller that the driver specified by

+                                This is managing.  This handle specifies the controller

+                                whose name is to be returned.

+  @param OPTIONAL   ChildHandle The handle of the child controller to retrieve the name

+                                of.  This is an optional parameter that may be NULL.  It

+                                will be NULL for device drivers.  It will also be NULL

+                                for a bus drivers that wish to retrieve the name of the

+                                bus controller.  It will not be NULL for a bus driver

+                                that wishes to retrieve the name of a child controller.

+  @param Language               A pointer to a three character ISO 639-2 language

+                                identifier.  This is the language of the controller name

+                                that that the caller is requesting, and it must match one

+                                of the languages specified in SupportedLanguages.  The

+                                number of languages supported by a driver is up to the

+                                driver writer.

+  @param ControllerName         A pointer to the Unicode string to return.  This Unicode

+                                string is the name of the controller specified by

+                                ControllerHandle and ChildHandle in the language

+                                specified by Language from the point of view of the

+                                driver specified by This.

+

+  @retval EFI_SUCCESS           The Unicode string for the user readable name in the

+                                language specified by Language for the driver

+                                specified by This was returned in DriverName.

+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.

+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid

+                                EFI_HANDLE.

+  @retval EFI_INVALID_PARAMETER Language is NULL.

+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently

+                                managing the controller specified by

+                                ControllerHandle and ChildHandle.

+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the

+                                language specified by Language.

+**/

+EFI_STATUS

+EFIAPI

+SataControllerComponentNameGetControllerName (

+  IN EFI_COMPONENT_NAME_PROTOCOL    *This,

+  IN EFI_HANDLE                     ControllerHandle,

+  IN EFI_HANDLE                     ChildHandle OPTIONAL,

+  IN CHAR8                          *Language,

+  OUT CHAR16                        **ControllerName

+  )

+;

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataControllerDxe.inf b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataControllerDxe.inf
new file mode 100644
index 0000000..b3b37dd
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SataControllerDxe/SataControllerDxe.inf
@@ -0,0 +1,49 @@
+## @file

+#  

+#    Component description file for the Sata Controller driver.

+#

+#  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>

+#  This program and the accompanying materials

+#  are licensed and made available under the terms and conditions of the BSD License

+#  which accompanies this distribution.  The full text of the license may be found at

+#  http://opensource.org/licenses/bsd-license.php

+#  

+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+#  

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = SataController

+  FILE_GUID                      = 8F4CD826-A5A0-4e93-9522-CFB0AB72926C

+  MODULE_TYPE                    = UEFI_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = InitializeSataControllerDriver

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC

+#

+

+[Sources]

+  ComponentName.c

+  SataController.c

+  SataController.h

+

+[Packages]

+  MdePkg/MdePkg.dec

+

+[LibraryClasses]

+  UefiDriverEntryPoint

+  DebugLib

+  UefiLib

+  BaseLib

+  BaseMemoryLib

+  MemoryAllocationLib

+  UefiBootServicesTableLib

+

+[Protocols]

+  gEfiPciIoProtocolGuid  

+  gEfiIdeControllerInitProtocolGuid

diff --git a/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.c b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.c
new file mode 100644
index 0000000..03e0936
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.c
@@ -0,0 +1,341 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name:

+

+  SmbiosGen.c

+

+Abstract:

+

+**/

+

+#include "SmbiosGen.h"

+EFI_HII_DATABASE_PROTOCOL   *gHiiDatabase;

+extern UINT8                SmbiosGenDxeStrings[];

+EFI_SMBIOS_PROTOCOL         *gSmbios;

+EFI_HII_HANDLE              gStringHandle;

+

+VOID *

+GetSmbiosTablesFromHob (

+  VOID

+  )

+{

+  EFI_PHYSICAL_ADDRESS       *Table;

+  EFI_PEI_HOB_POINTERS        GuidHob;

+

+  GuidHob.Raw = GetFirstGuidHob (&gEfiSmbiosTableGuid);

+  if (GuidHob.Raw != NULL) {

+    Table = GET_GUID_HOB_DATA (GuidHob.Guid);

+    if (Table != NULL) {

+      return (VOID *)(UINTN)*Table;

+    }

+  }

+

+  return NULL;

+}

+

+

+VOID

+InstallProcessorSmbios (

+  IN VOID                  *Smbios

+  )

+{

+  SMBIOS_STRUCTURE_POINTER          SmbiosTable;

+  CHAR8                             *AString;

+  CHAR16                            *UString;

+  STRING_REF                        Token;

+

+  //

+  // Processor info (TYPE 4)

+  // 

+  SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 4, 0);

+  if (SmbiosTable.Raw == NULL) {

+    DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 4 (Processor Info) not found!\n"));

+    return ;

+  }

+

+  //

+  // Log Smbios Record Type4

+  //

+  LogSmbiosData(gSmbios,(UINT8*)SmbiosTable.Type4);

+

+  //

+  // Set ProcessorVersion string

+  //

+  AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type4->ProcessorVersion);

+  UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16));

+  ASSERT (UString != NULL);

+  AsciiStrToUnicodeStr (AString, UString);

+

+  Token = HiiSetString (gStringHandle, 0, UString, NULL);

+  if (Token == 0) {

+    gBS->FreePool (UString);

+    return ;

+  }

+  gBS->FreePool (UString);

+  return ;

+}

+

+VOID

+InstallCacheSmbios (

+  IN VOID                  *Smbios

+  )

+{

+  return ;

+}

+

+VOID

+InstallMemorySmbios (

+  IN VOID                  *Smbios

+  )

+{

+  SMBIOS_STRUCTURE_POINTER          SmbiosTable;

+

+  //

+  // Generate Memory Array Mapped Address info (TYPE 19)

+  //

+  SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 19, 0);

+  if (SmbiosTable.Raw == NULL) {

+    DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 19 (Memory Array Mapped Address Info) not found!\n"));

+    return ;

+  }

+

+  //

+  // Record Smbios Type 19

+  //

+  LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type19);

+  return ;

+}

+

+VOID

+InstallMiscSmbios (

+  IN VOID                  *Smbios

+  )

+{

+  SMBIOS_STRUCTURE_POINTER          SmbiosTable;

+  CHAR8                             *AString;

+  CHAR16                            *UString;

+  STRING_REF                        Token;

+

+  //

+  // BIOS information (TYPE 0)

+  // 

+  SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 0, 0);

+  if (SmbiosTable.Raw == NULL) {

+    DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 0 (BIOS Information) not found!\n"));

+    return ;

+  }

+

+  //

+  // Record Type 2

+  //

+  AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type0->BiosVersion);

+  UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16) + sizeof(FIRMWARE_BIOS_VERSIONE));

+  ASSERT (UString != NULL);

+  CopyMem (UString, FIRMWARE_BIOS_VERSIONE, sizeof(FIRMWARE_BIOS_VERSIONE));

+  AsciiStrToUnicodeStr (AString, UString + sizeof(FIRMWARE_BIOS_VERSIONE) / sizeof(CHAR16) - 1);

+

+  Token = HiiSetString (gStringHandle, 0, UString, NULL);

+  if (Token == 0) {

+    gBS->FreePool (UString);

+    return ;

+  }

+  gBS->FreePool (UString);

+

+  //

+  // Log Smios Type 0

+  //

+  LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type0);

+  

+  //

+  // System information (TYPE 1)

+  // 

+  SmbiosTable = GetSmbiosTableFromType ((SMBIOS_TABLE_ENTRY_POINT *)Smbios, 1, 0);

+  if (SmbiosTable.Raw == NULL) {

+    DEBUG ((EFI_D_ERROR, "SmbiosTable: Type 1 (System Information) not found!\n"));

+    return ;

+  }

+

+  //

+  // Record Type 3

+  //

+  AString = GetSmbiosString (SmbiosTable, SmbiosTable.Type1->ProductName);

+  UString = AllocateZeroPool ((AsciiStrLen(AString) + 1) * sizeof(CHAR16) + sizeof(FIRMWARE_PRODUCT_NAME));

+  ASSERT (UString != NULL);

+  CopyMem (UString, FIRMWARE_PRODUCT_NAME, sizeof(FIRMWARE_PRODUCT_NAME));

+  AsciiStrToUnicodeStr (AString, UString + sizeof(FIRMWARE_PRODUCT_NAME) / sizeof(CHAR16) - 1);

+

+  Token = HiiSetString (gStringHandle, 0, UString, NULL);

+  if (Token == 0) {

+    gBS->FreePool (UString);

+    return ;

+  }

+  gBS->FreePool (UString);

+

+  //

+  // Log Smbios Type 1

+  //

+  LogSmbiosData(gSmbios, (UINT8*)SmbiosTable.Type1);

+  

+  return ;

+}

+

+EFI_STATUS

+EFIAPI

+SmbiosGenEntrypoint (

+  IN EFI_HANDLE           ImageHandle,

+  IN EFI_SYSTEM_TABLE     *SystemTable

+  )

+{

+  EFI_STATUS              Status;

+  VOID                    *Smbios;

+

+  Smbios = GetSmbiosTablesFromHob ();

+  if (Smbios == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  Status = gBS->LocateProtocol (

+                  &gEfiSmbiosProtocolGuid,

+                  NULL,

+                  (VOID**)&gSmbios

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->LocateProtocol (

+                  &gEfiHiiDatabaseProtocolGuid,

+                  NULL,

+                  (VOID**)&gHiiDatabase

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  

+  gStringHandle = HiiAddPackages (

+                    &gEfiCallerIdGuid,

+                    NULL,

+                    SmbiosGenDxeStrings,

+                    NULL

+                    );

+  ASSERT (gStringHandle != NULL);

+

+  InstallProcessorSmbios (Smbios);

+  InstallCacheSmbios     (Smbios);

+  InstallMemorySmbios    (Smbios);

+  InstallMiscSmbios      (Smbios);

+

+  return EFI_SUCCESS;

+}

+

+//

+// Internal function

+//

+

+UINTN

+SmbiosTableLength (

+  IN SMBIOS_STRUCTURE_POINTER SmbiosTable

+  )

+{

+  CHAR8  *AChar;

+  UINTN  Length;

+

+  AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);

+  while ((*AChar != 0) || (*(AChar + 1) != 0)) {

+    AChar ++;

+  }

+  Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2);

+  

+  return Length;

+}

+

+SMBIOS_STRUCTURE_POINTER

+GetSmbiosTableFromType (

+  IN SMBIOS_TABLE_ENTRY_POINT  *Smbios,

+  IN UINT8                     Type,

+  IN UINTN                     Index

+  )

+{

+  SMBIOS_STRUCTURE_POINTER SmbiosTable;

+  UINTN                    SmbiosTypeIndex;

+  

+  SmbiosTypeIndex = 0;

+  SmbiosTable.Raw = (UINT8 *)(UINTN)Smbios->TableAddress;

+  if (SmbiosTable.Raw == NULL) {

+    return SmbiosTable;

+  }

+  while ((SmbiosTypeIndex != Index) || (SmbiosTable.Hdr->Type != Type)) {

+    if (SmbiosTable.Hdr->Type == 127) {

+      SmbiosTable.Raw = NULL;

+      return SmbiosTable;

+    }

+    if (SmbiosTable.Hdr->Type == Type) {

+      SmbiosTypeIndex ++;

+    }

+    SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable));

+  }

+

+  return SmbiosTable;

+}

+

+CHAR8 *

+GetSmbiosString (

+  IN SMBIOS_STRUCTURE_POINTER  SmbiosTable,

+  IN SMBIOS_TABLE_STRING       String

+  )

+{

+  CHAR8      *AString;

+  UINT8      Index;

+

+  Index = 1;

+  AString = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);

+  while (Index != String) {

+    while (*AString != 0) {

+      AString ++;

+    }

+    AString ++;

+    if (*AString == 0) {

+      return AString;

+    }

+    Index ++;

+  }

+

+  return AString;

+}

+

+

+/**

+  Logs SMBIOS record.

+

+  @param  Smbios   Pointer to SMBIOS protocol instance.

+  @param  Buffer   Pointer to the data buffer.

+

+**/

+VOID

+LogSmbiosData (

+  IN   EFI_SMBIOS_PROTOCOL        *Smbios,

+  IN   UINT8                      *Buffer

+  )

+{

+  EFI_STATUS         Status;

+  EFI_SMBIOS_HANDLE  SmbiosHandle;

+  

+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+  Status = Smbios->Add (

+                     Smbios,

+                     NULL,

+                     &SmbiosHandle,

+                     (EFI_SMBIOS_TABLE_HEADER*)Buffer

+                     );

+  ASSERT_EFI_ERROR (Status);

+}

diff --git a/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.h b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.h
new file mode 100644
index 0000000..0474366
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.h
@@ -0,0 +1,79 @@
+/** @file

+

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

+This program and the accompanying materials                          

+are licensed and made available under the terms and conditions of the BSD License         

+which accompanies this distribution.  The full text of the license may be found at        

+http://opensource.org/licenses/bsd-license.php                                            

+                                                                                          

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+

+Module Name: 

+

+  DataHubGen.h

+

+Abstract:

+

+**/

+

+#ifndef _SMBIOS_GEN_H_

+#define _SMBIOS_GEN_H_

+

+#include <FrameworkDxe.h>

+#include <IndustryStandard/SmBios.h>

+

+#include <Guid/HobList.h>

+#include <Guid/SmBios.h>

+#include <Guid/DataHubRecords.h>

+

+#include <Protocol/Smbios.h>

+#include <Protocol/FrameworkHii.h>

+#include <Protocol/HiiDatabase.h>

+

+#include <Library/BaseLib.h>

+#include <Library/UefiLib.h>

+#include <Library/HobLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/HiiLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/MemoryAllocationLib.h>

+

+#define   PRODUCT_NAME                  L"DUET"

+#define   PRODUCT_VERSION               L"Beta"

+

+#define   FIRMWARE_PRODUCT_NAME         (PRODUCT_NAME L": ")

+#ifdef EFI32

+#define   FIRMWARE_BIOS_VERSIONE        (PRODUCT_NAME L"(IA32.UEFI)" PRODUCT_VERSION L": ")

+#else  // EFIX64

+#define   FIRMWARE_BIOS_VERSIONE        (PRODUCT_NAME L"(X64.UEFI)"  PRODUCT_VERSION L": ")

+#endif

+

+SMBIOS_STRUCTURE_POINTER

+GetSmbiosTableFromType (

+  IN SMBIOS_TABLE_ENTRY_POINT  *Smbios,

+  IN UINT8                 Type,

+  IN UINTN                 Index

+  );

+

+CHAR8 *

+GetSmbiosString (

+  IN SMBIOS_STRUCTURE_POINTER  SmbiosTable,

+  IN SMBIOS_TABLE_STRING       String

+  );

+

+/**

+  Logs SMBIOS record.

+

+  @param  Smbios   Pointer to SMBIOS protocol instance.

+  @param  Buffer   Pointer to the data buffer.

+

+**/

+VOID

+LogSmbiosData (

+  IN   EFI_SMBIOS_PROTOCOL        *Smbios,

+  IN   UINT8                      *Buffer

+  );

+

+#endif

diff --git a/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.inf b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.inf
new file mode 100644
index 0000000..e413beb
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGen.inf
@@ -0,0 +1,60 @@
+## @file

+#

+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>

+# This program and the accompanying materials                          

+# are licensed and made available under the terms and conditions of the BSD License         

+# which accompanies this distribution.  The full text of the license may be found at        

+# http://opensource.org/licenses/bsd-license.php                                            

+#                                                                                           

+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     

+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

+# 

+#  Module Name:

+#

+#    SmbiosGen.inf

+#

+#  Abstract:

+#

+#    Component description file for SmbiosGen module.

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = SmbiosGenDxe

+  FILE_GUID                      = A17F4A89-5F19-444f-B7BE-48195E0575DB

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = SmbiosGenEntrypoint

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  IntelFrameworkPkg/IntelFrameworkPkg.dec

+

+[LibraryClasses]

+  UefiLib

+  HobLib

+  UefiBootServicesTableLib

+  BaseMemoryLib

+  MemoryAllocationLib

+  UefiDriverEntryPoint

+  BaseLib

+  HiiLib

+  

+[Sources]

+  SmbiosGen.c

+  SmbiosGen.h

+  SmbiosGenStrings.uni

+

+[Guids]

+  gEfiSmbiosTableGuid

+

+[Protocols]

+  gEfiHiiDatabaseProtocolGuid

+  gEfiSmbiosProtocolGuid

+  gEfiHiiProtocolGuid

+  

+[Depex]

+  gEfiSmbiosProtocolGuid AND gEfiHiiDatabaseProtocolGuid

+

diff --git a/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGenStrings.uni b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGenStrings.uni
new file mode 100644
index 0000000..954ccd6
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/SmbiosGenDxe/SmbiosGenStrings.uni
Binary files differ
diff --git a/uefi/linaro-edk2/DuetPkg/build32.sh b/uefi/linaro-edk2/DuetPkg/build32.sh
new file mode 100755
index 0000000..5e99aba
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/build32.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+set -e
+shopt -s nocasematch
+
+
+#
+# Setup workspace if it is not set
+#
+if [ -z "$WORKSPACE" ]
+then
+  echo Initializing workspace
+  if [ ! -e `pwd`/edksetup.sh ]
+  then
+    cd ..
+  fi
+# This version is for the tools in the BaseTools project.
+# this assumes svn pulls have the same root dir
+#  export EDK_TOOLS_PATH=`pwd`/../BaseTools
+# This version is for the tools source in edk2
+  export EDK_TOOLS_PATH=`pwd`/BaseTools
+  echo $EDK_TOOLS_PATH
+  source edksetup.sh BaseTools
+else
+  echo Building from: $WORKSPACE
+fi
+
+PROCESSOR=IA32
+Processor=Ia32
+
+#
+# Pick a default tool type for a given OS
+#
+TARGET_TOOLS=MYTOOLS
+case `uname` in
+  CYGWIN*) echo Cygwin not fully supported yet. ;;
+  Darwin*)
+      Major=$(uname -r | cut -f 1 -d '.')
+      if [[ $Major == 9 ]]
+      then
+        echo DuetPkg requires Snow Leopard or later OS
+        exit 1
+      else
+        TARGET_TOOLS=XCODE32
+      fi
+      ;;
+  Linux*)
+    TARGET_TOOLS=GCC44
+    ;;
+
+esac
+
+BUILD_ROOT_ARCH=$WORKSPACE/Build/DuetPkg$PROCESSOR/DEBUG_"$TARGET_TOOLS"/$PROCESSOR
+FLOPPY_IMAGE=$WORKSPACE/Build/DuetPkg$PROCESSOR/floppy.img
+
+if  [[ ! -f `which build` || ! -f `which GenFv` ]];
+then
+  # build the tools if they don't yet exist. Bin scheme
+  echo Building tools as they are not in the path
+  make -C $WORKSPACE/BaseTools
+elif [[ ( -f `which build` ||  -f `which GenFv` )  && ! -d  $EDK_TOOLS_PATH/Source/C/bin ]];
+then
+  # build the tools if they don't yet exist. BinWrapper scheme
+  echo Building tools no $EDK_TOOLS_PATH/Source/C/bin directory
+  make -C $WORKSPACE/BaseTools
+else
+  echo using prebuilt tools
+fi
+
+
+for arg in "$@"
+do
+  if [[ $arg == qemu ]]; then
+    shift
+    qemu -fda $FLOPPY_IMAGE -boot a $*
+    exit
+  fi
+
+  if [[ $arg == cleanall ]]; then
+    make -C $WORKSPACE/BaseTools clean
+    build -p $WORKSPACE/DuetPkg/DuetPkg$Processor.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 clean
+    exit $?
+  fi
+
+  if [[ $arg == clean ]]; then
+    build -p $WORKSPACE/DuetPkg/DuetPkg$Processor.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 clean
+    exit $?
+  fi
+done
+
+
+#
+# Build the edk2 DuetPkg
+#
+echo Running edk2 build for DuetPkg$Processor
+build -p $WORKSPACE/DuetPkg/DuetPkg$Processor.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 $*
+echo Running DuetPkg/PostBuild.sh
+$WORKSPACE/DuetPkg/PostBuild.sh $PROCESSOR $TARGET_TOOLS
+echo Running DuetPkg/CreateBootDisk.sh
+
+$WORKSPACE/DuetPkg/CreateBootDisk.sh file $FLOPPY_IMAGE /dev/null FAT12 $PROCESSOR $TARGET_TOOLS
+exit $?
+
diff --git a/uefi/linaro-edk2/DuetPkg/build64.sh b/uefi/linaro-edk2/DuetPkg/build64.sh
new file mode 100755
index 0000000..d215116
--- /dev/null
+++ b/uefi/linaro-edk2/DuetPkg/build64.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+#
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+set -e
+shopt -s nocasematch
+
+
+#
+# Setup workspace if it is not set
+#
+if [ -z "$WORKSPACE" ]
+then
+  echo Initializing workspace
+  if [ ! -e `pwd`/edksetup.sh ]
+  then
+    cd ..
+  fi
+# This version is for the tools in the BaseTools project.
+# this assumes svn pulls have the same root dir
+#  export EDK_TOOLS_PATH=`pwd`/../BaseTools
+# This version is for the tools source in edk2
+  export EDK_TOOLS_PATH=`pwd`/BaseTools
+  echo $EDK_TOOLS_PATH
+  source edksetup.sh BaseTools
+else
+  echo Building from: $WORKSPACE
+fi
+
+PROCESSOR=X64
+
+#
+# Pick a default tool type for a given OS
+#
+TARGET_TOOLS=MYTOOLS
+case `uname` in
+  CYGWIN*) echo Cygwin not fully supported yet. ;;
+  Darwin*)
+      Major=$(uname -r | cut -f 1 -d '.')
+      if [[ $Major == 9 ]]
+      then
+        echo DuetPkg requires Snow Leopard or later OS
+        exit 1
+      else
+        TARGET_TOOLS=XCODE32
+      fi
+      ;;
+  Linux*)
+    TARGET_TOOLS=GCC44
+    ;;
+
+esac
+
+BUILD_ROOT_ARCH=$WORKSPACE/Build/DuetPkg$PROCESSOR/DEBUG_"$TARGET_TOOLS"/$PROCESSOR
+FLOPPY_IMAGE=$WORKSPACE/Build/DuetPkg$PROCESSOR/floppy.img
+
+if  [[ ! -f `which build` || ! -f `which GenFv` ]];
+then
+  # build the tools if they don't yet exist. Bin scheme
+  echo Building tools as they are not in the path
+  make -C $WORKSPACE/BaseTools
+elif [[ ( -f `which build` ||  -f `which GenFv` )  && ! -d  $EDK_TOOLS_PATH/Source/C/bin ]];
+then
+  # build the tools if they don't yet exist. BinWrapper scheme
+  echo Building tools no $EDK_TOOLS_PATH/Source/C/bin directory
+  make -C $WORKSPACE/BaseTools
+else
+  echo using prebuilt tools
+fi
+
+
+for arg in "$@"
+do
+  if [[ $arg == qemu ]]; then
+    shift
+    qemu-system-x86_64 -fda $FLOPPY_IMAGE -boot a $*
+    exit
+  fi
+
+  if [[ $arg == cleanall ]]; then
+    make -C $WORKSPACE/BaseTools clean
+    build -p $WORKSPACE/DuetPkg/DuetPkg$PROCESSOR.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 clean
+    exit $?
+  fi
+
+  if [[ $arg == clean ]]; then
+    build -p $WORKSPACE/DuetPkg/DuetPkg$PROCESSOR.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 clean
+    exit $?
+  fi
+done
+
+
+#
+# Build the edk2 DuetPkg
+#
+echo Running edk2 build for DuetPkg$PROCESSOR
+build -p $WORKSPACE/DuetPkg/DuetPkg$PROCESSOR.dsc -a $PROCESSOR -t $TARGET_TOOLS -n 3 $*
+echo Running DuetPkg/PostBuild.sh
+$WORKSPACE/DuetPkg/PostBuild.sh $PROCESSOR $TARGET_TOOLS
+echo Running DuetPkg/CreateBootDisk.sh
+
+$WORKSPACE/DuetPkg/CreateBootDisk.sh file $FLOPPY_IMAGE /dev/null FAT12 $PROCESSOR $TARGET_TOOLS
+exit $?
+