summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rwxr-xr-x[-rw-r--r--]MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c6
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c9
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c1
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h3
-rwxr-xr-x[-rw-r--r--]MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c11
-rw-r--r--MdeModulePkg/Include/Guid/Hostname.h27
-rw-r--r--MdeModulePkg/Include/Library/PathLib.h56
-rw-r--r--MdeModulePkg/Library/BasePathLib/BasePathLib.c131
-rw-r--r--MdeModulePkg/Library/BasePathLib/BasePathLib.inf38
-rw-r--r--MdeModulePkg/MdeModulePkg.dec4
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc2
-rw-r--r--MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystem.c569
-rw-r--r--MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemDxe.inf52
-rw-r--r--MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemEntryPoint.c401
-rw-r--r--MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemInternal.h99
-rw-r--r--MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c35
-rw-r--r--MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h1
-rw-r--r--MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf1
18 files changed, 1442 insertions, 4 deletions
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
index 3fcb0f991..a3eb14b28 100644..100755
--- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
@@ -1095,6 +1095,12 @@ EhcAsyncInterruptTransfer (
EhcLinkQhToPeriod (Ehc, Urb->Qh);
InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);
+ // ARM: Force an asynchonous transfer after waiting an interval
+ // Polling interval is in milliseconds while BS.Stall except
+ // Microseconds.
+ gBS->Stall (PollingInterval * 1000);
+ EhcMonitorAsyncRequests (Ehc->PollTimer, Ehc);
+
ON_EXIT:
Ehc->PciIo->Flush (Ehc->PciIo);
gBS->RestoreTPL (OldTpl);
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
index 5594e6699..cc6e77e38 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
@@ -573,6 +573,12 @@ EhcCheckUrbResult (
ASSERT ((Ehc != NULL) && (Urb != NULL) && (Urb->Qh != NULL));
+ // The URB is already being processed, we do not want the callback to be
+ // called twice for the same URB
+ if (Urb->InProgress) {
+ return FALSE;
+ }
+
Finished = TRUE;
Urb->Completed = 0;
@@ -992,6 +998,9 @@ EhcMonitorAsyncRequests (
continue;
}
+ // Mark the URB as 'in-progress' to prevent the URB to be processed twice.
+ Urb->InProgress = TRUE;
+
//
// Flush any PCI posted write transactions from a PCI host
// bridge to system memory.
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c
index 6afb327df..1ad37d5bd 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.c
@@ -600,6 +600,7 @@ EhcCreateUrb (
Urb->DataLen = DataLen;
Urb->Callback = Callback;
Urb->Context = Context;
+ Urb->InProgress = FALSE;
PciIo = Ehc->PciIo;
Urb->Qh = EhcCreateQh (Ehc, &Urb->Ep);
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h b/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h
index 02e9af81b..0c80e7624 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciUrb.h
@@ -232,7 +232,8 @@ struct _URB {
// Transaction result
//
UINT32 Result;
- UINTN Completed; // completed data length
+ BOOLEAN InProgress; // defined when the URB is being processed
+ UINTN Completed; // Length of the data being processed
UINT8 DataToggle;
};
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
index e3752d1f8..be07a740c 100644..100755
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
@@ -668,7 +668,10 @@ UsbOnHubInterrupt (
}
CopyMem (HubIf->ChangeMap, Data, DataLength);
- gBS->SignalEvent (HubIf->HubNotify);
+
+ //ARM: We do not use BS.SignalEvent in order to initialize the new device immediately
+ //gBS->SignalEvent (HubIf->HubNotify);
+ UsbHubEnumeration (HubIf->HubNotify, HubIf);
return EFI_SUCCESS;
}
@@ -1112,7 +1115,11 @@ UsbRootHubInit (
// It should signal the event immediately here, or device detection
// by bus enumeration might be delayed by the timer interval.
//
- gBS->SignalEvent (HubIf->HubNotify);
+
+ //ARM: We invoke the function directly to ensure the enumeration is
+ // done immediately.
+ //gBS->SignalEvent (HubIf->HubNotify);
+ UsbRootHubEnumeration (NULL, HubIf);
Status = gBS->SetTimer (
HubIf->HubNotify,
diff --git a/MdeModulePkg/Include/Guid/Hostname.h b/MdeModulePkg/Include/Guid/Hostname.h
new file mode 100644
index 000000000..4e79dc712
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/Hostname.h
@@ -0,0 +1,27 @@
+/** @file
+*
+* Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* 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 __HOSTNAME_GUID_H__
+#define __HOSTNAME_GUID_H__
+
+/*
+ This Variable guid is used for the UEFI variable named "Hostname".
+ A use case for this is Ip4ConfigDxe sending a hostname during the DHCP DORA
+ process. A future version of the UEFI spec might include this variable in
+ the list of globally defined variables. In this case this GUID would become
+ redundant and gEfiGlobalVariableGuid could be used instead.
+*/
+extern EFI_GUID gEfiHostnameVariableGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Library/PathLib.h b/MdeModulePkg/Include/Library/PathLib.h
new file mode 100644
index 000000000..ee473523d
--- /dev/null
+++ b/MdeModulePkg/Include/Library/PathLib.h
@@ -0,0 +1,56 @@
+/** @file
+ Provides interface to path manipulation functions.
+
+ 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 _PATH_LIB_
+#define _PATH_LIB_
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+
+/**
+ Removes the last directory or file entry in a path by changing the last
+ L'\' to a CHAR_NULL.
+
+ @param[in, out] Path The pointer to the path to modify.
+
+ @retval FALSE Nothing was found to remove.
+ @retval TRUE A directory or file was removed.
+**/
+BOOLEAN
+EFIAPI
+PathRemoveLastItem(
+ IN OUT CHAR16 *Path
+ );
+
+/**
+ Function to clean up paths.
+
+ - Single periods in the path are removed.
+ - Double periods in the path are removed along with a single parent directory.
+ - Forward slashes L'/' are converted to backward slashes L'\'.
+
+ This will be done inline and the existing buffer may be larger than required
+ upon completion.
+
+ @param[in] Path The pointer to the string containing the path.
+
+ @retval NULL An error occured.
+ @return Path in all other instances.
+**/
+CHAR16*
+EFIAPI
+PathCleanUpDirectories(
+ IN CHAR16 *Path
+ );
+
+#endif //_PATH_LIB_
diff --git a/MdeModulePkg/Library/BasePathLib/BasePathLib.c b/MdeModulePkg/Library/BasePathLib/BasePathLib.c
new file mode 100644
index 000000000..301bd3b27
--- /dev/null
+++ b/MdeModulePkg/Library/BasePathLib/BasePathLib.c
@@ -0,0 +1,131 @@
+/** @file
+ Provides interface to path manipulation functions.
+
+ Copyright (c) 2011 - 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.
+**/
+
+#include <Base.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PathLib.h>
+#include <Library/BaseLib.h>
+#include <Protocol/SimpleTextIn.h>
+
+/**
+ Removes the last directory or file entry in a path by changing the last
+ L'\' to a CHAR_NULL.
+
+ @param[in, out] Path The pointer to the path to modify.
+
+ @retval FALSE Nothing was found to remove.
+ @retval TRUE A directory or file was removed.
+**/
+BOOLEAN
+EFIAPI
+PathRemoveLastItem(
+ IN OUT CHAR16 *Path
+ )
+{
+ CHAR16 *Walker;
+ CHAR16 *LastSlash;
+ //
+ // get directory name from path... ('chop' off extra)
+ //
+ for ( Walker = Path, LastSlash = NULL
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Walker++
+ ){
+ if (*Walker == L'\\' && *(Walker + 1) != CHAR_NULL) {
+ LastSlash = Walker+1;
+ }
+ }
+ if (LastSlash != NULL) {
+ *LastSlash = CHAR_NULL;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Function to clean up paths.
+
+ - Single periods in the path are removed.
+ - Double periods in the path are removed along with a single parent directory.
+ - Forward slashes L'/' are converted to backward slashes L'\'.
+
+ This will be done inline and the existing buffer may be larger than required
+ upon completion.
+
+ @param[in] Path The pointer to the string containing the path.
+
+ @retval NULL An error occured.
+ @return Path in all other instances.
+**/
+CHAR16*
+EFIAPI
+PathCleanUpDirectories(
+ IN CHAR16 *Path
+ )
+{
+ CHAR16 *TempString;
+ UINTN TempSize;
+ if (Path==NULL) {
+ return(NULL);
+ }
+
+ //
+ // Fix up the '/' vs '\'
+ //
+ for (TempString = Path ; TempString != NULL && *TempString != CHAR_NULL ; TempString++) {
+ if (*TempString == L'/') {
+ *TempString = L'\\';
+ }
+ }
+
+ //
+ // Fix up the ..
+ //
+ while ((TempString = StrStr(Path, L"\\..\\")) != NULL) {
+ *TempString = CHAR_NULL;
+ TempString += 4;
+ PathRemoveLastItem(Path);
+ TempSize = StrSize(TempString);
+ CopyMem(Path+StrLen(Path), TempString, TempSize);
+ }
+ if ((TempString = StrStr(Path, L"\\..")) != NULL && *(TempString + 3) == CHAR_NULL) {
+ *TempString = CHAR_NULL;
+ PathRemoveLastItem(Path);
+ }
+
+ //
+ // Fix up the .
+ //
+ while ((TempString = StrStr(Path, L"\\.\\")) != NULL) {
+ *TempString = CHAR_NULL;
+ TempString += 2;
+ TempSize = StrSize(TempString);
+ CopyMem(Path+StrLen(Path), TempString, TempSize);
+ }
+ if ((TempString = StrStr(Path, L"\\.")) != NULL && *(TempString + 2) == CHAR_NULL) {
+ *(TempString + 1) = CHAR_NULL;
+ }
+
+ while ((TempString = StrStr(Path, L"\\\\")) != NULL) {
+ *TempString = CHAR_NULL;
+ TempString += 1;
+ TempSize = StrSize(TempString);
+ CopyMem(Path+StrLen(Path), TempString, TempSize);
+ }
+ if ((TempString = StrStr(Path, L"\\\\")) != NULL && *(TempString + 1) == CHAR_NULL) {
+ *(TempString) = CHAR_NULL;
+ }
+
+ return (Path);
+}
+
diff --git a/MdeModulePkg/Library/BasePathLib/BasePathLib.inf b/MdeModulePkg/Library/BasePathLib/BasePathLib.inf
new file mode 100644
index 000000000..734696878
--- /dev/null
+++ b/MdeModulePkg/Library/BasePathLib/BasePathLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Provides interface to path manipulation functions.
+#
+# 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 = 0x00010006
+ BASE_NAME = BasePathLib
+ FILE_GUID = ED244F93-B97A-4a17-83E0-A03CF2A7F7B4
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PathLib|UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ BasePathLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib \ No newline at end of file
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index c5c5ab106..b74d3a08e 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -180,6 +180,10 @@
## Include/Guid/NicIp4ConfigNvData.h
gEfiNicIp4ConfigVariableGuid = {0xd8944553, 0xc4dd, 0x41f4, { 0x9b, 0x30, 0xe1, 0x39, 0x7c, 0xfb, 0x26, 0x7b }}
+ ## GUID for variable to save hostname
+ # Include/Guid/Hostname.h
+ gEfiHostnameVariableGuid = {0x0CA6824E, 0x989A, 0x11E3, { 0x84, 0xF9, 0x47, 0x67, 0x26, 0x2D, 0x11, 0xE1 }}
+
## Include/Guid/StatusCodeCallbackGuid.h
gStatusCodeCallbackGuid = {0xe701458c, 0x4900, 0x4ca5, {0xb7, 0x72, 0x3d, 0x37, 0x94, 0x9f, 0x79, 0x27}}
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index f7a88ffb2..715e58233 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -334,6 +334,8 @@
NULL|MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf
}
+ MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemDxe.inf
+
[Components.IA32, Components.X64, Components.IPF]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
diff --git a/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystem.c b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystem.c
new file mode 100644
index 000000000..5071befd3
--- /dev/null
+++ b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystem.c
@@ -0,0 +1,569 @@
+/** @file
+*
+* Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+*
+**/
+
+/*
+ A driver using the EFI_FIRMWARE_VOLUME2_PROTOCOL to expose files in firmware
+ volumes via the the EFI_SIMPLE_FILESYSTEM_PROTOCOL and EFI_FILE_PROTOCOL.
+
+ Its primary intended use is to be able to start EFI applications embedded
+ in FVs from the UEFI shell. For this reason, it is not fully compliant as a
+ filesystem driver: it is entirely read-only, and does not support partially
+ reading files.
+
+ It will expose a single directory, containing one file for each file in the
+ firmware volume. If a file has a UI section, its contents will be used as
+ a filename. Otherwise, a string representation of the GUID will be used.
+ Files of an executable type (That is PEIM, DRIVER, COMBINED_PEIM_DRIVER
+ and APPLICATION) will have ".efi" added to their filename.
+
+ The data returned by Read() depends on the type of the underlying FV file:
+ - For executable types, the first section found that contains executable code
+ is returned.
+ - For files of type FREEFORM, the driver attempts to return the first section
+ of type RAW. If none is found, the entire contents of the FV file are
+ returned.
+ - On all other files the entire contents of the FV file is returned, as by
+ EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadFile.
+
+ See the EFI Firmware Volume specification (a separate document from the main
+ UEFI specification) for more information about firmware volumes.
+*/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PathLib.h>
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+#include "FvSimpleFilesystemInternal.h"
+
+/*
+ Find and call ReadSection on the first section found of an executable type.
+*/
+STATIC
+EFI_STATUS
+FvFsFindExecutableSection (
+ IN FV_FILESYSTEM_FILE *File,
+ OUT UINTN *BufferSize,
+ OUT VOID **Buffer
+ )
+{
+ EFI_SECTION_TYPE SectionType;
+ UINT32 AuthenticationStatus;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ EFI_STATUS Status;
+
+ FvProtocol = File->Instance->FvProtocol;
+
+ for (SectionType = EFI_SECTION_PE32; SectionType <= EFI_SECTION_TE; SectionType++) {
+ Status = FvProtocol->ReadSection (
+ FvProtocol,
+ &File->NameGuid,
+ SectionType,
+ 0,
+ Buffer,
+ BufferSize,
+ &AuthenticationStatus
+ );
+ if (Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+/*
+ Get the size of the buffer that will be returned by FvFsReadFile.
+*/
+EFI_STATUS
+FvFsGetFileSize (
+ IN FV_FILESYSTEM_FILE *File,
+ OUT UINTN *Size
+ )
+{
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ UINT32 AuthenticationStatus;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ EFI_STATUS Status;
+ UINT8 IgnoredByte;
+ VOID *IgnoredPtr;
+
+ FvProtocol = File->Instance->FvProtocol;
+
+ // To get the size of a section, we pass 0 for BufferSize. But we can't pass
+ // NULL for Buffer, as that will cause a return of INVALID_PARAMETER, and we
+ // can't pass NULL for *Buffer, as that will cause the callee to allocate
+ // a buffer of the sections size.
+ IgnoredPtr = &IgnoredByte;
+ *Size = 0;
+
+ if (FV_FILETYPE_IS_EXECUTABLE (File->Type)) {
+ // Get the size of the first executable section out of the file.
+ Status = FvFsFindExecutableSection (File, Size, &IgnoredPtr);
+ if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
+ return EFI_SUCCESS;
+ }
+ } else if (File->Type == EFI_FV_FILETYPE_FREEFORM) {
+ // Try to get the size of a raw section out of the file
+ Status = FvProtocol->ReadSection (
+ FvProtocol,
+ &File->NameGuid,
+ EFI_SECTION_RAW,
+ 0,
+ &IgnoredPtr,
+ Size,
+ &AuthenticationStatus
+ );
+ if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
+ return EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ // Didn't find a raw section, just return the whole file's size.
+ return FvProtocol->ReadFile (
+ FvProtocol,
+ &File->NameGuid,
+ NULL,
+ Size,
+ &FoundType,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ }
+ } else {
+ // Get the size of the entire file
+ return FvProtocol->ReadFile (
+ FvProtocol,
+ &File->NameGuid,
+ NULL,
+ Size,
+ &FoundType,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ }
+
+ return Status;
+}
+
+/*
+ Helper function to read a file. See comment at the top of this file for
+ information on behaviour.
+*/
+EFI_STATUS
+FvFsReadFile (
+ FV_FILESYSTEM_FILE *File,
+ UINTN *BufferSize,
+ VOID **Buffer
+ )
+{
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ UINT32 AuthenticationStatus;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ EFI_STATUS Status;
+
+ FvProtocol = File->Instance->FvProtocol;
+
+ if (FV_FILETYPE_IS_EXECUTABLE (File->Type)) {
+ // Read the first executable section out of the file.
+ Status = FvFsFindExecutableSection (File, BufferSize, Buffer);
+ } else if (File->Type == EFI_FV_FILETYPE_FREEFORM) {
+ // Try to read a raw section out of the file
+ Status = FvProtocol->ReadSection (
+ FvProtocol,
+ &File->NameGuid,
+ EFI_SECTION_RAW,
+ 0,
+ Buffer,
+ BufferSize,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ // Didn't find a raw section, just return the whole file.
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &File->NameGuid,
+ Buffer,
+ BufferSize,
+ &FoundType,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ }
+ } else {
+ // Read the entire file
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &File->NameGuid,
+ Buffer,
+ BufferSize,
+ &FoundType,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ }
+
+ return Status;
+}
+
+/*
+ Helper function for populating an EFI_FILE_INFO for a file.
+*/
+STATIC
+EFI_STATUS
+FvFsGetFileInfo (
+ IN FV_FILESYSTEM_FILE *File,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_FILE_INFO *FileInfo
+ )
+{
+ UINTN InfoSize;
+
+ InfoSize = sizeof (EFI_FILE_INFO) + StrSize (File->Name) - sizeof (CHAR16);
+ if (*BufferSize < InfoSize) {
+ *BufferSize = InfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Initialize FileInfo
+ ZeroMem (FileInfo, InfoSize);
+ FileInfo->Size = InfoSize;
+ FileInfo->Attribute = EFI_FILE_READ_ONLY;
+
+ // File is a directory if it is root.
+ if (File == File->Instance->Root) {
+ FileInfo->Attribute |= EFI_FILE_DIRECTORY;
+ }
+
+ FileInfo->FileSize = File->Size;
+ FileInfo->PhysicalSize = File->Size;
+
+ StrCpy (FileInfo->FileName, File->Name);
+
+ *BufferSize = InfoSize;
+ return EFI_SUCCESS;
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ FV_FILESYSTEM_INSTANCE *Instance;
+ FV_FILESYSTEM_FILE *File;
+ LIST_ENTRY *FileLink;
+
+ if ((FileName == NULL) || (NewHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The only valid modes are read, read/write, and read/write/create
+ if ( (OpenMode != EFI_FILE_MODE_READ) &&
+ (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) &&
+ (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ if (OpenMode & EFI_FILE_MODE_CREATE) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ File = FVFS_FILE_FROM_FILE_THIS (This);
+ Instance = File->Instance;
+
+ FileName = PathCleanUpDirectories (FileName);
+
+ if (FileName[0] == L'\\') {
+ FileName++;
+ }
+
+ // Check for opening root
+ if (StrCmp (FileName, L".") == 0 || StrCmp (FileName, L"") == 0) {
+ *NewHandle = &Instance->Root->FileProtocol;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Do a linear search for a file in the FV with a matching filename
+ //
+ for (FileLink = GetFirstNode (&Instance->Files);
+ !IsNull (&Instance->Files, FileLink);
+ FileLink = GetNextNode (&Instance->Files, FileLink)) {
+
+ File = FVFS_FILE_FROM_LINK (FileLink);
+ if (mUnicodeCollation->StriColl (mUnicodeCollation, File->Name, FileName) == 0) {
+ *NewHandle = &File->FileProtocol;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemClose (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/*
+ Implementation of EFI_FILE_PROTOCOL.Read.
+
+ This implementation is not compliant with the UEFI specification. As this
+ driver's only intended use case is for loading and executing EFI images,
+ it does not support partial reads. If *BufferSize is less than the size of the
+ image being read, it will return EFI_UNSUPPORTED.
+*/
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ FV_FILESYSTEM_INSTANCE *Instance;
+ FV_FILESYSTEM_FILE *File;
+ EFI_STATUS Status;
+ LIST_ENTRY *FileLink;
+
+ File = FVFS_FILE_FROM_FILE_THIS (This);
+ Instance = File->Instance;
+
+ if (File == Instance->Root) {
+ if (File->DirReadNext) {
+ //
+ // Directory read: populate Buffer with an EFI_FILE_INFO
+ //
+ Status = FvFsGetFileInfo (File->DirReadNext, BufferSize, Buffer);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Successfully read a directory entry, now update the pointer to the
+ // next file, which will be read on the next call to this function
+ //
+
+ FileLink = GetNextNode (&Instance->Files, &File->DirReadNext->Link);
+ if (IsNull (&Instance->Files, FileLink)) {
+ // No more files left
+ File->DirReadNext = NULL;
+ } else {
+ File->DirReadNext = FVFS_FILE_FROM_LINK (FileLink);
+ }
+ }
+ return Status;
+ } else {
+ //
+ // Directory read. All entries have been read, so return a zero-size
+ // buffer.
+ //
+ *BufferSize = 0;
+ return EFI_SUCCESS;
+ }
+ } else {
+ if (*BufferSize < File->Size) {
+ DEBUG ((EFI_D_ERROR, "FV Filesystem does not support partial file reads\n", *BufferSize, File->Size));
+ return EFI_UNSUPPORTED;
+ }
+ return FvFsReadFile (File, BufferSize, &Buffer);
+ }
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/*
+ This implementation of EFI_FILE_PROTOCOL.SetPosition is not compliant with
+ the UEFI specification. We do not support partial file reads (see comment on
+ FvSimpleFilesystemRead), therefore we only support seeking to position 0
+*/
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ FV_FILESYSTEM_INSTANCE *Instance;
+ FV_FILESYSTEM_FILE *File;
+
+ File = FVFS_FILE_FROM_FILE_THIS (This);
+ Instance = File->Instance;
+
+ if (File == Instance->Root) {
+ if (Position != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ // Reset directory position to first entry
+ File->DirReadNext = FVFS_GET_FIRST_FILE (Instance);
+ } else if (Position != 0) {
+ // We don't support partial file reads, so we don't support seeking either.
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemFlush (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemDelete (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return EFI_WARN_DELETE_FAILURE;
+}
+
+STATIC EFI_FILE_SYSTEM_INFO mFsInfoTemplate = {
+ 0, // Populate at runtime
+ TRUE, // Read-only
+ 0, // Don't know volume size
+ 0, // No free space
+ 0, // Don't know block size
+ L"" // Populate at runtime
+};
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ FV_FILESYSTEM_FILE *File;
+ EFI_FILE_SYSTEM_INFO *FsInfoOut;
+ FV_FILESYSTEM_INSTANCE *Instance;
+ UINTN InfoSize;
+
+ File = FVFS_FILE_FROM_FILE_THIS (This);
+
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ //
+ // Return filesystem info
+ //
+ Instance = File->Instance;
+
+ InfoSize = sizeof (EFI_FILE_SYSTEM_INFO) + StrSize (Instance->VolumeLabel)
+ - sizeof (CHAR16);
+
+ if (*BufferSize < InfoSize) {
+ *BufferSize = InfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Cast output buffer for convenience
+ FsInfoOut = (EFI_FILE_SYSTEM_INFO *) Buffer;
+ mFsInfoTemplate.Size = InfoSize;
+
+ CopyMem (FsInfoOut, &mFsInfoTemplate, sizeof(EFI_FILE_SYSTEM_INFO));
+ StrCpy (FsInfoOut->VolumeLabel, Instance->VolumeLabel);
+ return EFI_SUCCESS;
+ } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ //
+ // Return file info
+ //
+
+ return FvFsGetFileInfo (File, BufferSize, (EFI_FILE_INFO *) Buffer);
+ } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ //
+ // Return Volume Label
+ //
+ Instance = File->Instance;
+ InfoSize = StrSize (Instance->VolumeLabel);
+
+ if (*BufferSize >= InfoSize) {
+ StrCpy (Buffer, Instance->VolumeLabel);
+ return EFI_SUCCESS;
+ } else {
+ *BufferSize = InfoSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_WRITE_PROTECTED;
+}
+
+EFI_FILE_PROTOCOL mFilesystemTemplate = {
+ EFI_FILE_PROTOCOL_REVISION,
+ FvSimpleFilesystemOpen,
+ FvSimpleFilesystemClose,
+ FvSimpleFilesystemDelete,
+ FvSimpleFilesystemRead,
+ FvSimpleFilesystemWrite,
+ FvSimpleFilesystemGetPosition,
+ FvSimpleFilesystemSetPosition,
+ FvSimpleFilesystemGetInfo,
+ FvSimpleFilesystemSetInfo,
+ FvSimpleFilesystemFlush
+};
diff --git a/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemDxe.inf b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemDxe.inf
new file mode 100644
index 000000000..9d4200405
--- /dev/null
+++ b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemDxe.inf
@@ -0,0 +1,52 @@
+#/** @file
+# Support for Simple File System over Firmware Volume
+#
+# Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# 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 = FvSimpleFilesystem
+ FILE_GUID = 907125c0-a5f1-11e3-a3fe-a3198b49350c
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FvSimpleFilesystemEntryPoint
+
+[Sources]
+ FvSimpleFilesystem.c
+ FvSimpleFilesystemEntryPoint.c
+ FvSimpleFilesystemInternal.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DevicePathLib
+ MemoryAllocationLib
+ PathLib
+ PrintLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gEfiFileInfoGuid
+ gEfiFileSystemInfoGuid
+ gEfiFileSystemVolumeLabelInfoIdGuid
+
+[Protocols]
+ gEfiDevicePathFromTextProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiDriverBindingProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gEfiUnicodeCollationProtocolGuid
diff --git a/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemEntryPoint.c b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemEntryPoint.c
new file mode 100644
index 000000000..2828f8aed
--- /dev/null
+++ b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemEntryPoint.c
@@ -0,0 +1,401 @@
+/** @file
+*
+* Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* 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 <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include "FvSimpleFilesystemInternal.h"
+
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
+
+// A Guid string is 32 hex characters with 4 hyphens: 36 characters total
+#define GUID_STRING_SIZE (36 * sizeof (CHAR16))
+
+#define FVFS_VOLUME_LABEL_PREFIX L"Firmware Volume: "
+#define FVFS_VOLUME_LABEL_SIZE (sizeof (FVFS_VOLUME_LABEL_PREFIX) + GUID_STRING_SIZE)
+#define FVFS_FALLBACK_VOLUME_LABEL L"Firmware Volume"
+
+EFI_STATUS
+EFIAPI
+FvSimpleFilesystemOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **RootFile
+ )
+{
+ EFI_STATUS Status;
+ FV_FILESYSTEM_FILE *Root;
+ CHAR16 *UiSection;
+ EFI_GUID NameGuid;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINT32 Authentication;
+ VOID *Key;
+ EFI_FV_FILETYPE FileType;
+ UINTN Size;
+ FV_FILESYSTEM_INSTANCE *Instance;
+ FV_FILESYSTEM_FILE *File;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ CHAR16 *Name;
+
+ Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This);
+ Status = EFI_SUCCESS;
+
+ if (Instance->Root == NULL) {
+ //
+ // Allocate file structure for root file
+ //
+ Root = AllocatePool (sizeof (FV_FILESYSTEM_FILE));
+ if (Root == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->Root = Root;
+
+ Root->Instance = Instance;
+ Root->Signature = FVFS_FILE_SIGNATURE;
+ Root->Name = L"";
+ Root->Size = 0;
+ CopyMem (&Root->FileProtocol, &mFilesystemTemplate, sizeof (mFilesystemTemplate));
+
+ //
+ // Populate the instance's list of files. We consider anything a file that
+ // has a UI_SECTION, which we consider to be its filename.
+ //
+
+ FvProtocol = Instance->FvProtocol;
+
+ // Allocate Key
+ Key = AllocatePool (FvProtocol->KeySize);
+ ASSERT (Key != NULL);
+ ZeroMem (Key, FvProtocol->KeySize);
+
+ do {
+ FileType = EFI_FV_FILETYPE_ALL;
+
+ Status = FvProtocol->GetNextFile (
+ FvProtocol,
+ Key,
+ &FileType,
+ &NameGuid,
+ &Attributes,
+ &Size
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status == EFI_NOT_FOUND);
+ break;
+ }
+
+ //
+ // Found a file.
+ // Allocate a file structure and populate it.
+ //
+ File = AllocatePool (sizeof (FV_FILESYSTEM_FILE));
+ if (File == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get a file's name: If it has a UI section, use that, otherwise use
+ // its NameGuid.
+ //
+
+ UiSection = NULL;
+ Status = FvProtocol->ReadSection (
+ FvProtocol,
+ &NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **)&UiSection,
+ &Size,
+ &Authentication
+ );
+ if (!EFI_ERROR (Status)) {
+ Name = UiSection;
+ } else {
+ Name = AllocatePool (GUID_STRING_SIZE);
+ if (Name == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid);
+ }
+
+ // Add ".efi" to filenames of drivers and applications.
+ if (FV_FILETYPE_IS_EXECUTABLE (FileType)) {
+ File->Name = AllocateCopyPool (StrSize (Name) + 8, Name);
+ StrCat (File->Name, L".efi");
+ FreePool (Name);
+ } else {
+ File->Name = Name;
+ }
+
+ File->Type = FileType;
+ File->Signature = FVFS_FILE_SIGNATURE;
+ CopyGuid (&File->NameGuid, &NameGuid);
+ File->Instance = Instance;
+ CopyMem (&File->FileProtocol, &mFilesystemTemplate, sizeof (mFilesystemTemplate));
+ InsertHeadList (&Instance->Files, &File->Link);
+
+ // Call FvFsReadFile to get the file's size
+ File->Size = 0;
+ Status = FvFsGetFileSize (File, &File->Size);
+ ASSERT_EFI_ERROR (Status);
+ } while (TRUE);
+
+ FreePool (Key);
+
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE (Instance);
+ *RootFile = &Instance->Root->FileProtocol;
+ return Status;
+}
+
+STATIC EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mSimpleFsTemplate = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ FvSimpleFilesystemOpenVolume
+};
+
+EFI_STATUS
+EFIAPI
+FvSimpleFilesystemDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL
+ )
+{
+ return gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+}
+
+EFI_STATUS
+EFIAPI
+FvSimpleFilesystemDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ FV_FILESYSTEM_INSTANCE *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;
+ EFI_GUID *FvGuid;
+
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollationProtocolGuid,
+ NULL,
+ (VOID **) &mUnicodeCollation
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open FV protocol
+ //
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **) &FvProtocol,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create an instance
+ //
+ Instance = AllocatePool (sizeof (FV_FILESYSTEM_INSTANCE));
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->Root = NULL;
+ Instance->FvProtocol = FvProtocol;
+ Instance->Signature = FVFS_INSTANCE_SIGNATURE;
+ InitializeListHead (&Instance->Files);
+ CopyMem (&Instance->SimpleFs, &mSimpleFsTemplate, sizeof (mSimpleFsTemplate));
+
+ Status = gBS->InstallProtocolInterface(
+ &ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Instance->SimpleFs
+ );
+
+ //
+ // Decide on a filesystem volume label, which will include the FV's guid.
+ //
+
+ // Get the device path to find the FV's GUID
+ Instance->VolumeLabel = NULL;
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &FvDevicePath,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ // Iterate over device path until we find a firmware volume node
+ while (!IsDevicePathEndType (FvDevicePath)) {
+ if (DevicePathType (FvDevicePath) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (FvDevicePath) == MEDIA_PIWG_FW_VOL_DP) {
+ // Allocate the volume label
+ Instance->VolumeLabel = AllocatePool (FVFS_VOLUME_LABEL_SIZE);
+ // Check the allocation was successful
+ if (Instance->VolumeLabel != NULL) {
+ // Extract the FV's guid
+ FvGuid = &((MEDIA_FW_VOL_DEVICE_PATH *) FvDevicePath)->FvName;
+ // Build the volume label string
+ UnicodeSPrint (
+ Instance->VolumeLabel,
+ FVFS_VOLUME_LABEL_SIZE,
+ FVFS_VOLUME_LABEL_PREFIX L"%g",
+ FvGuid
+ );
+ }
+ break;
+ }
+ FvDevicePath = NextDevicePathNode (FvDevicePath);
+ }
+ }
+ // If we didn't decide on a volume label, set a fallback one
+ if (Instance->VolumeLabel == NULL) {
+ Instance->VolumeLabel = AllocateCopyPool (
+ sizeof (FVFS_FALLBACK_VOLUME_LABEL),
+ FVFS_FALLBACK_VOLUME_LABEL
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FvSimpleFilesystemDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ FV_FILESYSTEM_INSTANCE *Instance;
+ FV_FILESYSTEM_FILE *File;
+ LIST_ENTRY *FileLink;
+
+ Instance = FVFS_INSTANCE_FROM_BINDING_THIS (DriverBinding);
+
+ //
+ // Close and uninstall protocols.
+ //
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ gImageHandle,
+ ControllerHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->UninstallProtocolInterface (
+ ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ &Instance->SimpleFs
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Free file structures
+ //
+
+ if (Instance->Root != NULL) {
+ for (FileLink = GetFirstNode (&Instance->Files);
+ !IsNull (&Instance->Files, FileLink);
+ FileLink = GetNextNode (&Instance->Files, FileLink)) {
+ File = FVFS_FILE_FROM_LINK (FileLink);
+
+ FreePool (File->Name);
+ FreePool (File);
+ }
+ // Root->Name is statically allocated, no need to free.
+ FreePool (Instance->Root);
+ }
+
+ //
+ // Free Instance
+ //
+
+ if (Instance->VolumeLabel != NULL) {
+ FreePool (Instance->VolumeLabel);
+ }
+ FreePool (Instance);
+
+ return EFI_SUCCESS;
+}
+
+EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
+ FvSimpleFilesystemDriverSupported,
+ FvSimpleFilesystemDriverStart,
+ FvSimpleFilesystemDriverStop,
+ 0,
+ NULL,
+ NULL
+};
+
+EFIAPI
+EFI_STATUS
+FvSimpleFilesystemEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mDriverBinding
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemInternal.h b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemInternal.h
new file mode 100644
index 000000000..ecf5461a0
--- /dev/null
+++ b/MdeModulePkg/Universal/FvSimpleFilesystemDxe/FvSimpleFilesystemInternal.h
@@ -0,0 +1,99 @@
+/** @file
+*
+* Copyright (c) 2014, ARM Limited. All rights reserved.
+*
+* This program and the accompanying materials
+* are licensed and made available under the terms and conditions of the BSD License
+* which accompanies this distribution. The full text of the license may be found at
+* http://opensource.org/licenses/bsd-license.php
+*
+* 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 __FVFS_INTERNAL_H__
+#define __FVFS_INTERNAL_H__
+
+#include <Library/BaseLib.h>
+
+typedef struct _FV_FILESYSTEM_FILE FV_FILESYSTEM_FILE;
+
+// Struct representing an instance of the "filesystem". There will be one of
+// these structs per FV.
+typedef struct _FV_FILESYSTEM_INSTANCE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ LIST_ENTRY Files;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs;
+ FV_FILESYSTEM_FILE *Root;
+ CHAR16 *VolumeLabel;
+} FV_FILESYSTEM_INSTANCE;
+
+// Struct representing a file. There will be one of these for each file on each
+// FV, plus one for each FV representing the "root directory".
+struct _FV_FILESYSTEM_FILE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ CHAR16 *Name;
+ FV_FILESYSTEM_FILE *DirReadNext;
+ EFI_GUID NameGuid;
+ FV_FILESYSTEM_INSTANCE *Instance;
+ EFI_FILE_PROTOCOL FileProtocol;
+ UINTN Size;
+ EFI_FV_FILETYPE Type;
+};
+
+#define FVFS_FILE_SIGNATURE SIGNATURE_32 ('f', 'v', 'f', 'l')
+#define FVFS_INSTANCE_SIGNATURE SIGNATURE_32 ('f', 'v', 'f', 's')
+
+#define FVFS_INSTANCE_FROM_BINDING_THIS(This) CR ( \
+ This, \
+ FV_FILESYSTEM_INSTANCE, \
+ DriverBinding, \
+ FVFS_INSTANCE_SIGNATURE \
+ )
+
+#define FVFS_INSTANCE_FROM_SIMPLE_FS_THIS(This) CR ( \
+ This, \
+ FV_FILESYSTEM_INSTANCE, \
+ SimpleFs, \
+ FVFS_INSTANCE_SIGNATURE \
+ )
+
+#define FVFS_FILE_FROM_FILE_THIS(This) CR ( \
+ This, \
+ FV_FILESYSTEM_FILE, \
+ FileProtocol, \
+ FVFS_FILE_SIGNATURE \
+ )
+
+#define FVFS_FILE_FROM_LINK(FileLink) CR (FileLink, FV_FILESYSTEM_FILE, Link, FVFS_FILE_SIGNATURE)
+
+#define FVFS_GET_FIRST_FILE(Instance) FVFS_FILE_FROM_LINK (GetFirstNode (&Instance->Files))
+
+#define FV_FILETYPE_IS_EXECUTABLE(Type) ((Type) == EFI_FV_FILETYPE_PEIM || \
+ (Type) == EFI_FV_FILETYPE_DRIVER || \
+ (Type) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER || \
+ (Type) == EFI_FV_FILETYPE_APPLICATION)
+
+EFI_STATUS
+FvFsReadFile (
+ FV_FILESYSTEM_FILE *File,
+ UINTN *BufferSize,
+ VOID **Buffer
+ );
+
+EFI_STATUS
+FvFsGetFileSize (
+ IN FV_FILESYSTEM_FILE *File,
+ OUT UINTN *Size
+ );
+
+extern EFI_FILE_PROTOCOL mFilesystemTemplate;
+
+extern EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation;
+
+#endif
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
index 3eff1882e..be08fcee9 100644
--- a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
+++ b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
@@ -15,6 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "Ip4Config.h"
#include "NicIp4Variable.h"
+#include <Guid/Hostname.h>
+
//
// Ip4 Config Protocol
//
@@ -327,11 +329,14 @@ EfiIp4ConfigStart (
IP4_CONFIG_INSTANCE *Instance;
EFI_DHCP4_PROTOCOL *Dhcp4;
EFI_DHCP4_MODE_DATA Dhcp4Mode;
- EFI_DHCP4_PACKET_OPTION *OptionList[1];
+ EFI_DHCP4_PACKET_OPTION *OptionList[2];
IP4_CONFIG_DHCP4_OPTION ParaList;
EFI_STATUS Status;
UINT32 Source;
EFI_TPL OldTpl;
+ CHAR8 Hostname[256];
+ UINTN HostnameSize = 256;
+ EFI_DHCP4_PACKET_OPTION *HostnameOption = NULL;
if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -436,8 +441,36 @@ EfiIp4ConfigStart (
Dhcp4Mode.ConfigData.OptionCount = 1;
Dhcp4Mode.ConfigData.OptionList = OptionList;
+ Status = gRT->GetVariable (
+ L"Hostname",
+ &gEfiHostnameVariableGuid,
+ NULL,
+ &HostnameSize,
+ &Hostname
+ );
+ if (!EFI_ERROR (Status) && HostnameSize != 0) {
+ Dhcp4Mode.ConfigData.OptionCount = 2;
+
+ HostnameOption = AllocatePool (
+ sizeof (EFI_DHCP4_PACKET_OPTION) - 1 + HostnameSize
+ );
+ if (HostnameOption == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HostnameOption->OpCode = DHCP_TAG_HOSTNAME;
+ HostnameOption->Length = (UINT8) HostnameSize;
+ CopyMem (HostnameOption->Data, Hostname, HostnameOption->Length);
+
+ OptionList[1] = HostnameOption;
+ }
+
Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);
+ if (HostnameOption) {
+ FreePool (HostnameOption);
+ }
+
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h
index cbe8ec5fc..449881499 100644
--- a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h
+++ b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h
@@ -59,6 +59,7 @@ extern EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate;
#define IP4_CONFIG_STATE_STARTED 1
#define IP4_CONFIG_STATE_CONFIGURED 2
+#define DHCP_TAG_HOSTNAME 12
#define DHCP_TAG_PARA_LIST 55
#define DHCP_TAG_NETMASK 1
#define DHCP_TAG_ROUTER 3
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
index c1199828b..8a199370c 100644
--- a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
+++ b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
@@ -86,6 +86,7 @@
## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData EFI_NIC_IP4_CONFIG_VARIABLE
## SOMETIMES_CONSUMES ## HII
gNicIp4ConfigNvDataGuid
+ gEfiHostnameVariableGuid ## CONSUMES ## Guid
[UserExtensions.TianoCore."ExtraFiles"]
Ip4ConfigDxeExtra.uni