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 $?
+