summaryrefslogtreecommitdiff
path: root/Core/EM/Recovery
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /Core/EM/Recovery
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'Core/EM/Recovery')
-rw-r--r--Core/EM/Recovery/CapsuleRecovery.c278
-rw-r--r--Core/EM/Recovery/FsRecovery.c3193
-rw-r--r--Core/EM/Recovery/IdeRecovery.c2172
-rw-r--r--Core/EM/Recovery/ReFlash/Esrt.c415
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.c601
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.cif16
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.dxs72
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.h268
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.mak135
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.sdl135
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.unibin0 -> 13216 bytes
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.vfr240
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlashWorker.c720
-rw-r--r--Core/EM/Recovery/Recovery.c720
-rw-r--r--Core/EM/Recovery/Recovery.cif16
-rw-r--r--Core/EM/Recovery/Recovery.dxs57
-rw-r--r--Core/EM/Recovery/Recovery.h113
-rw-r--r--Core/EM/Recovery/Recovery.mak116
-rw-r--r--Core/EM/Recovery/Recovery.sdl235
-rw-r--r--Core/EM/Recovery/RecoveryCsp.h849
-rw-r--r--Core/EM/Recovery/RecoverySrc.cif13
-rw-r--r--Core/EM/Recovery/RecoverySrc.mak81
-rw-r--r--Core/EM/Recovery/RecoverySrc.sdl21
-rw-r--r--Core/EM/Recovery/SerialRecovery.c1047
24 files changed, 11513 insertions, 0 deletions
diff --git a/Core/EM/Recovery/CapsuleRecovery.c b/Core/EM/Recovery/CapsuleRecovery.c
new file mode 100644
index 0000000..f38c11e
--- /dev/null
+++ b/Core/EM/Recovery/CapsuleRecovery.c
@@ -0,0 +1,278 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/CapsuleRecovery.c 2 4/16/13 5:51a Thomaschen $
+//
+// $Revision: 2 $
+//
+// $Date: 4/16/13 5:51a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/CapsuleRecovery.c $
+//
+// 2 4/16/13 5:51a Thomaschen
+// Fixed for EIP106722.
+//
+// 4 2/07/13 5:17p Artems
+// [TAG] EIP106722
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] Win8 firmware update doesn't work
+// [RootCause] For Win8 update capsule CapsuleRecovery device didn't
+// skip capsule header
+// [Solution] Added unique GUID to distinguish between AFU and Win8
+// capsule update
+// [Files] Capsule2_0.c CapsuleRecovery.c Capsule.h
+//
+// 3 11/15/12 4:28p Artems
+// [TAG] EIP103898
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] After updating Core 4.6.5.4, the Capsule mode of Secure
+// Flash can't work.
+// [RootCause] Capsule recovery device was stripping capsule header from
+// provided image,
+// but verification code requires header to be present
+// [Solution] Keep header together with recovery image for verification
+// purposes
+// [Files] CapsuleRecovery.c
+//
+// 2 9/17/12 2:50p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Removed unnecessary debug messages
+// [Files] CapsuleRecovery.c
+//
+// 1 8/02/12 12:04p Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Windows 8 firmware update spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c CapsuleRecovery.c
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: CapsuleRecovery.c
+//
+// Description: Recovery from Capsule support
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiPeiLib.h>
+#include <AmiHobs.h>
+#include <Capsule.h>
+#include <Token.h>
+#include "Recovery.h"
+#include "RecoveryCsp.h"
+
+
+/************************************************************************/
+/* Device Recovery Module PPI */
+/************************************************************************/
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetNumberRecoveryCapsules
+//
+// Description:
+// GetNumberRecoveryCapsules function of ppi
+// EFI_PEI_DEVICE_RECOVERY_MODULE_PPI.
+//
+// Input:
+//
+// Output:
+// EFI_SUCCESS - number of recovery capsules returned
+// EFI_INVALID_PARAMETER - the pointer NumberRecoveryCapsules is NULL
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+static EFI_STATUS GetNumberRecoveryCapsules(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ OUT UINTN *NumberRecoveryCapsules
+)
+{
+ if ( !NumberRecoveryCapsules ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *NumberRecoveryCapsules = 1;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetRecoveryCapsuleInfo
+//
+// Description:
+// GetRecoveryCapsuleInfo function of ppi EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+// for any block devices including floppies, USB keys, CD-ROMs and HDDs.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PeiServices Structure
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This - pointer to the PPI structure
+// IN UINTN CapsuleInstance - value indicating the instance of the PPI
+// OUT UINTN *Size - Size of the recovery capsule
+// OUT EFI_GUID *CapsuleType OPTIONAL - Type of recovery capsule
+//
+// Output:
+// EFI_SUCCESS - Parameters are valid and output parameters are updated
+// EFI_INVALID_PARAMETER - Size pointer is NULL
+// EFI_NOT_FOUND - asking for a 1 or greater instance of the PPI
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS GetRecoveryCapsuleInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT UINTN *Size,
+ OUT EFI_GUID *CapsuleType )
+{
+ EFI_STATUS Status;
+ if ( !Size ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( CapsuleInstance > 0 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetRecoveryFileInfo(PeiServices, NULL, Size, NULL);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if ( CapsuleType ) {
+ *CapsuleType = guidOemCapsule;
+ }
+ return EFI_SUCCESS;
+}
+
+#define NUMBER_OF_RETRIES 3
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: LoadRecoveryCapsule
+//
+// Description:
+// Locates all EFI_PEI_RECOVERY_BLOCK_IO_PPI PPIs. Calls function
+// GetNumberOfBlockDevices. For each block device, calls the function
+// FsRecoveryRead, to find the recovery image named in var sAmiRomFile.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PeiServices Structure
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This - pointer to the PPI structure
+// IN UINTN CapsuleInstance - value indicating the instance of the PPI
+// OUT VOID *Buffer - contains information read from the block device
+//
+// Output:
+// EFI_SUCCESS - File read from recovery media
+// EFI_INVALID_PARAMETER - Buffer is a NULL pointer
+// EFI_NOT_FOUND - asking for a 1 or greater instance of the PPI
+// Other - return error values from LocatePpi or FsRecoveryRead
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ AMI_CAPSULE_HOB *CapsuleHob;
+ static EFI_GUID CapsuleHobGuid = AMI_CAPSULE_HOB_GUID;
+ static EFI_GUID AptioFwCapsuleGuid = APTIO_FW_CAPSULE_GUID;
+ static EFI_GUID W8FwUpdateImageCapsuleGuid = W8_FW_UPDATE_IMAGE_CAPSULE_GUID;
+ EFI_CAPSULE_HEADER *Capsule;
+ VOID *Data;
+ UINTN CapsuleSize;
+
+ Status = (*PeiServices)->GetHobList(PeiServices, &CapsuleHob);
+ if(EFI_ERROR(Status))
+ return EFI_SUCCESS;
+
+ do {
+ Status = FindNextHobByGuid(&CapsuleHobGuid, &CapsuleHob);
+ if(!EFI_ERROR(Status)) {
+ Capsule = (EFI_CAPSULE_HEADER *)(VOID *)(UINTN)(CapsuleHob->CapsuleData);
+ if(!guidcmp(&AptioFwCapsuleGuid, &(CapsuleHob->CapsuleGuid))) { //we found AFU recovery capsule, let's keep capsule header and put into provided buffer
+ MemCpy(Buffer, Capsule, Capsule->CapsuleImageSize);
+ return EFI_SUCCESS;
+ }
+ if(!guidcmp(&W8FwUpdateImageCapsuleGuid, &(CapsuleHob->CapsuleGuid))) { //we found Win8 recovery capsule, let's skip capsule header and put into provided buffer
+ CapsuleSize = Capsule->CapsuleImageSize - Capsule->HeaderSize;
+ Data = (VOID *)((UINT8 *)Capsule + Capsule->HeaderSize);
+ MemCpy(Buffer, Data, CapsuleSize);
+ return EFI_SUCCESS;
+ }
+ }
+ } while(!EFI_ERROR(Status));
+
+ return Status;
+}
+
+/************************************************************************/
+/* Entry Point */
+/************************************************************************/
+EFI_PEI_DEVICE_RECOVERY_MODULE_PPI CapsuleDeviceRecoveryModule = {
+ GetNumberRecoveryCapsules, GetRecoveryCapsuleInfo, LoadRecoveryCapsule
+};
+
+// PPI to be installed
+static EFI_PEI_PPI_DESCRIPTOR CapsuleDeviceRecoveryPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidRecoveryDevice, &CapsuleDeviceRecoveryModule
+ }
+};
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: CapsuleDeviceRecoveryEntry
+//
+// Description:
+// Installs EFI_PEI_DEVICE_RECOVERY_MODULE_PPI for loading recovery
+// images from APTIO_FW_CAPSULE_GUID capsule
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CapsuleDeviceRecoveryEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ return (*PeiServices)->InstallPpi( PeiServices, CapsuleDeviceRecoveryPpiList );
+}
+
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/FsRecovery.c b/Core/EM/Recovery/FsRecovery.c
new file mode 100644
index 0000000..b16d7b0
--- /dev/null
+++ b/Core/EM/Recovery/FsRecovery.c
@@ -0,0 +1,3193 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/Recovery/FsRecovery.c 22 8/09/12 11:13a Pats $
+//
+// $Revision: 22 $
+//
+// $Date: 8/09/12 11:13a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/Recovery/FsRecovery.c $
+//
+// 22 8/09/12 11:13a Pats
+// [TAG] - EIP 80780
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the
+// EXT(x) file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 21 4/24/12 11:43a Pats
+// [TAG] EIP87223
+// [Category] Bug Fix
+// [Symptom] After update EIP#81131 solution, the MBR recovery function
+// would fail
+// [RootCause] Pointer *Root not being updated correctly in function
+// AmiGetFileListFromNtfsVolume().
+// [Solution] Correct updating of pointer *Root.
+//
+// [Files] FsRecovery.c
+//
+// 20 1/25/12 2:49p Pats
+// [TAG] - EIP 26909
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the NTFS
+// file system. This of necessity includes detection of GPT partitions,
+// which may contain any file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 19 5/13/11 5:07p Artems
+// Added secure flash update support
+//
+// 18 2/05/11 3:22p Artems
+// EIP 39463: Added support to override GetFileName function for custom
+// recovery capsule name
+//
+// 17 6/11/10 11:36a Artems
+// Added porting hooks for GetRecoveryCapsuleFileName and
+// IsRecoveryCapsuleValid
+//
+// 16 1/05/10 11:59a Robert
+// Fixed bug in calculation of byte offset of the beginning of a file on a
+// FAT file system. The old code could not handle a file starting address
+// above 4GB. It now uses a UINT64 calculation so it can handle it
+//
+// 15 11/25/09 4:53p Felixp
+// sAmiRomFile renamed to RecoveryFileName
+// FlashSize renamed ro RecoveryImageSize
+//
+// 14 8/11/09 2:27p Robert
+// - EIP 24689: There was a bug in the wildcard search with FAT that
+// caused it not to identify the file properly.
+// - The code was expecting string termination. Switched to filename
+// length instead. Updated both the FAT file search and the ISO9660
+// search with this.
+// - Also added a check for the FAT file system that checks for the 0xE5
+// character that defines an invalid or deleted file.
+//
+// 13 7/09/09 12:54p Artems
+// Removed PeiTrace debugging calls
+//
+// 12 7/07/09 2:05p Robert
+// - Added functionality to search for recovery files that fit one of many
+// comma separated pattern strings.
+// - Function header updates
+//
+// 11 7/01/09 4:18p Rameshr
+// Coding Standard and File header updated.
+//
+// 10 6/16/09 5:21p Artems
+// EIP 21169 Added Eltorito support
+//
+// 7 4/13/07 5:37p Ambikas
+// Coding standards changes: Added AMI_PHDRs for every function; split
+// multiple declarations on a line into single line statements.
+//
+// 6 10/13/06 11:07a Felixp
+// 1. el Torito support added
+// 2. Correct partition handling
+//
+// 5 9/26/06 9:22a Ambikas
+//
+// 4 6/04/06 9:29p Ambikas
+//
+// 3 4/13/06 2:02p Ambikas
+//
+// 1 12/01/05 9:45a Felixp
+//
+// 4 11/18/05 3:55p Felixp
+// bug fix in ReadFileData
+//
+// 3 6/06/05 1:27p Felixp
+// Type parameter removed from AllocatePages to match PEI CIS 0.91
+//
+// 2 3/25/05 5:41p Felixp
+// small bug fix
+//
+// 1 3/24/05 3:37p Felixp
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: FsRecovery.c
+//
+// Description: Recovery Filesytem support
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <AmiPeiLib.h>
+#include <Token.h>
+#include "Recovery.h"
+#include "RecoveryCsp.h"
+
+#define FAT_FILE_NAME_SIZE 11
+
+extern BOOLEAN CdRecoverySupport;
+extern BOOLEAN FatRecoverySupport;
+extern BOOLEAN NtfsRecoverySupport;
+extern BOOLEAN ExtRecoverySupport;
+
+UINT8 *ReadBuffer = NULL;
+UINTN BufferSize = 0;
+
+UINT8 *FatBuffer = NULL;
+UINTN FatBufferSize = 0;
+
+UINT8 *RootBuffer = NULL;
+UINTN RootBufferSize = 0;
+UINT32 RootEntries = 0;
+UINT32 RootSize = 0;
+
+DIR_ENTRY *FatRecoveryFiles[10];
+DIR_RECORD *CdRecoveryFiles[10];
+#if NTFS_RECOVERY_SUPPORT
+INDEX_ENTRY *NtfsRecoveryFiles[10];
+
+//UINT8 MFTRunList[256];
+//UINT8 RootRunList[128];
+//UINT8 ResidentIndex[256];
+BOOLEAN ResidentPresent;
+UINT32 ResidentSize;
+#endif
+#if EXT_RECOVERY_SUPPORT
+DIR_ENTRY_EXT *ExtRecoveryFiles[10];
+UINT32 InodeBlock; // First block of inode table
+UINT8 Indirect;
+UINT32 *BlockList;
+UINT32 *BlockList2;
+#endif
+
+UINTN PartCount;
+BOOLEAN IsMbr;
+UINT32 GpeCount;
+UINT32 PartSector;
+//MASTER_BOOT_RECORD Mbr;
+MEMORY_BLOCK *MemBlk;
+
+EFI_PEI_SERVICES **ThisPeiServices;
+#if SEARCH_FAT_PATH
+RC_VOL_INFO *ThisVolume; // Saved volume info for path search
+#endif
+
+//***************************************************************************
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: toupper
+//
+// Description:
+// Converts lower case characters to upper case
+//
+// Input:
+// IN CHAR8 c - character to convert
+//
+// Output:
+// CHAR8 - converted character value
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+CHAR8 toupper(
+ IN CHAR8 c )
+{
+ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FileCompare
+//
+// Description:
+// This function takes a filename and a filename pattern and tries to make
+// a match. It can account for Wild characters * and ? in the pattern. Also,
+// the pattern can be multiple comma separated patterns.
+//
+// Input:
+// IN CHAR8 *RecoveryFileName - recover file pattern string comma separated
+// IN CHAR8 *FsFilename - file name to check against the pattern string
+// IN BOOLEAN IgnoreSpacesInFilename - If true, ignore spaces in FsFilename when pattern string is a period
+//
+// Output:
+// TRUE - Pattern matches filename
+// FALSE - Pattern doesn't match filename
+//
+// Notes:
+// RecoveryFileNamePattern is taken from the RECOVERY_ROM token and should look
+// like this: *.rom,ab??rt??.bio,123.bin etc.
+// The Parameter IgnoreSpacesInFilename is for use with file systems that pad
+// spaces into filenames and don't use periods. If TRUE, it matches a period
+// in the pattern to any number of spaces in the filename.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN FileCompare(
+ IN CHAR8 *RecoveryFileNamePattern,
+ IN CHAR8 *FsFilename,
+ IN BOOLEAN IgnoreSpacesInFilename,
+ IN UINT32 FileNameLength)
+{
+ CHAR8 ch1, ch;
+ UINTN len1, len2;
+
+ for (; ;) {
+ // check length of string
+ len1 = Strlen(FsFilename);
+ len2 = Strlen(RecoveryFileNamePattern);
+
+ // if len1 is 0 then at end of filename
+ if(!len1 || !FileNameLength)
+ {
+ // if len2 is 0 then also at end of pattern so file name is
+ // equal to a pattern
+ if(!len2 )
+ return TRUE;
+ else
+ {
+ // if len2 is a comma, then it is the same as len2 == 0 so
+ // file name is equal to a pattern
+ ch1 = *RecoveryFileNamePattern;
+ if (ch1 == ',')
+ {
+ return TRUE;
+ }
+ // if not a comma or 0, then file does not fit the pattern
+ return FALSE;
+ }
+ }
+
+ // get next character of the pattern
+ ch1 = *RecoveryFileNamePattern;
+ RecoveryFileNamePattern ++;
+
+ switch (ch1)
+ {
+ case ',':
+ return TRUE;
+ break;
+
+ case 0: // reached string terminator
+ return TRUE;
+ break;
+
+ // wild character, it must deal with any number of matching characters
+ // in the file name string
+ case '*':
+ while (*FsFilename)
+ {
+ if (FileCompare (RecoveryFileNamePattern, FsFilename, IgnoreSpacesInFilename, FileNameLength))
+ {
+ return TRUE;
+ }
+ FsFilename ++;
+ FileNameLength--;
+ }
+ return FileCompare (RecoveryFileNamePattern, FsFilename, IgnoreSpacesInFilename, FileNameLength);
+ break;
+
+ // wild character, it must deal with a matching character in the file name string
+ case '?':
+ if (!*FsFilename)
+ {
+ return FALSE;
+ }
+
+ FsFilename ++;
+ FileNameLength--;
+ break;
+
+ // in this case statement the case '.' must be directly above the default case.
+ // if IgnoreSpacesInFilename is FALSE, it is supposed to fall through into default.
+ // If IgnoreSpacesInFilenameis TRUE, process the period as a check for spaces character.
+ // then once we skip over all spaces, if there are any, then it moves to the
+ // next character in the pattern
+ case '.':
+ // FAT, spaces added to file name to make 8 3 -- no period in the filename either
+ if (IgnoreSpacesInFilename == TRUE)
+ {
+ ch = *FsFilename;
+
+ while ((ch == ' ') && (ch != 0))
+ {
+ FsFilename ++;
+ FileNameLength--;
+ ch = *FsFilename;
+ }
+ break;
+ }
+ // CDFS, no spaces and there is a period. Let it fall through to the default case
+ default:
+ ch = *FsFilename;
+ if (toupper(ch) != toupper(ch1))
+ {
+ return FALSE;
+ }
+ FsFilename ++;
+ FileNameLength--;
+ break;
+ }
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FileSearch
+//
+// Description:
+// Wrapper function for parsing through a pattern string with multiple entries
+// Each entry is comma separated and can include wild characters like * and ?
+// The Function can handle CDFS and FAT file systems.
+//
+// Input:
+// IN CHAR8 *RecoveryFileName - recover file pattern string comma separated
+// IN CHAR8 *FsFilename - file name to check against the pattern string
+// IN BOOLEAN IgnoreSpacesInFilename - If true, ignore spaces in FsFilename when pattern string is a period
+//
+// Output:
+// EFI_SUCCESS - File name fits one of the Pattern strings in RecoveryFileName
+// EFI_INVALID_PARAMETER - one of the strings is NULL or file name doesn't fit pattern string
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FileSearch(
+ IN CHAR8 *RecoveryFileName,
+ IN CHAR8 *FsFilename,
+ IN BOOLEAN IgnoreSpacesInFilename,
+ IN UINT32 FileNameLength)
+{
+ CHAR8 *RecStrPtr = RecoveryFileName;
+ CHAR8 *FilenamePtr = FsFilename;
+
+ if (*RecStrPtr == 0)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*FsFilename == 0)
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FileNameLength == 0 )
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ // loop until all possibilities listed in the RecoveryFileName are exhausted
+ do {
+ // Now compare the current possiblity to the current filename
+ FilenamePtr = FsFilename;
+
+ if (*RecStrPtr == ',')
+ RecStrPtr++;
+
+ if (FileCompare(RecStrPtr, FsFilename, IgnoreSpacesInFilename, FileNameLength) == TRUE)
+ return EFI_SUCCESS;
+
+ while (*RecStrPtr != ',' && *RecStrPtr != 0)
+ RecStrPtr ++;
+
+ } while (*RecStrPtr != 0);
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ConvertToFatFileName
+//
+// Description:
+// Converts file name from "XXXXX.XXX" form to FAT form
+//
+// Input:
+// IN CHAR8 *inFileName - pointer to input file name
+// OUT CHAR8 *outFileName - pointer to output file name
+//
+// Output: None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ConvertToFatFileName(
+ IN CHAR8 *inFileName,
+ OUT CHAR8 *outFileName )
+{
+ UINT32 i = 0;
+ UINT32 j = 0;
+
+ for ( i = 0; inFileName[i] && inFileName[i] != '.'; i++ ) {
+ outFileName[i] = toupper( inFileName[i] );
+ }
+ j = i;
+
+ for (; i < 8; i++ ) {
+ outFileName[i] = ' ';
+ }
+
+ if ( inFileName[j] == '.' ) {
+ for ( j++; inFileName[j]; i++, j++ ) {
+ outFileName[i] = toupper( inFileName[j] );
+ }
+ }
+
+ for (; i < 11; i++ ) {
+ outFileName[i] = ' ';
+ }
+ outFileName[i] = 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadDevice
+//
+// Description: Reads data from Block device
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN RC_VOL_INFO *Volume - pointer to volume description structure
+// IN UINT64 Start - starting offset in bytes
+// IN UINTN Size - size of the data to read
+// VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_SUCCESS
+// Errors
+// - returns either the error status from Allocate Pages or Read Blocks
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN RC_VOL_INFO *Volume,
+ IN UINT64 Start,
+ IN UINTN Size,
+ OUT VOID *Buffer )
+{
+ UINT64 StartLba;
+ UINTN ActualSize;
+ UINTN ActualPages;
+ UINT32 StartOffset;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ Start += Volume->PartitionOffset;
+
+ if ( Volume->BlockSize == 4096 ) {
+ StartLba = Shr64( Start, 12 );
+ StartOffset = (UINT32)( Start & 0xfff );
+ } else if ( Volume->BlockSize == 2048 ) {
+ StartLba = Shr64( Start, 11 );
+ StartOffset = (UINT32)( Start & 0x7ff );
+ } else {
+ StartLba = Shr64( Start, 9 );
+ StartOffset = (UINT32)( Start & 0x1ff );
+ }
+
+ ActualSize = ((StartOffset + Size + Volume->BlockSize - 1) / Volume->BlockSize) * Volume->BlockSize;
+ ActualPages = EFI_SIZE_TO_PAGES( ActualSize );
+
+ if ( BufferSize < EFI_PAGES_TO_SIZE( ActualPages )) {
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, ActualPages, &Allocate );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ ReadBuffer = (UINT8*)((UINTN)Allocate);
+ BufferSize = EFI_PAGES_TO_SIZE( ActualPages );
+ }
+
+ Status = Volume->BlkIo->ReadBlocks( PeiServices,
+ Volume->BlkIo,
+ Volume->Device,
+ StartLba,
+ ActualSize,
+ ReadBuffer );
+
+ if ( !EFI_ERROR( Status )) {
+ MemCpy( Buffer, ReadBuffer + StartOffset, Size );
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsFat
+//
+// Description:
+// Checks if given data block describes FAT structure
+//
+// Input:
+// BOOT_SECTOR *pBpb - pointer to data block to check
+//
+// Output:
+// TRUE - data block is a FAT structure
+// FALSE - data block is not a FAT structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsFat(
+ IN BOOT_SECTOR *pBpb )
+{
+ return pBpb->BytsPerSec <= 4096
+ && pBpb->SecPerClus && pBpb->SecPerClus <= 128
+ && pBpb->RsvdSecCnt
+ && pBpb->NumFATs
+ && pBpb->Signature == 0xAA55
+ && (pBpb->jmp[0] == 0xEB || pBpb->jmp[0] == 0xE9);
+}
+
+#if NTFS_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsNtfs
+//
+// Description:
+// Checks if given data block describes NTFS structure
+//
+// Input:
+// BOOT_SECTOR *pBpb - pointer to data block to check
+//
+// Output:
+// TRUE - data block is a NTFS structure
+// FALSE - data block is not a NTFS structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsNtfs(
+ IN BOOT_SECTOR *pBpb )
+{
+ return pBpb->NumFATs == 0
+ && pBpb->TotSec16 == 0
+ && pBpb->TotSec32 == 0
+ && pBpb->Fat.Ntfs.TotSec64 != 0
+ && pBpb->OEMName[0] == 0x4E // Name must be "NTFS"
+ && pBpb->OEMName[1] == 0x54
+ && pBpb->OEMName[2] == 0x46
+ && pBpb->OEMName[3] == 0x53
+ && pBpb->Signature == 0xAA55
+ && (pBpb->jmp[0] == 0xEB || pBpb->jmp[0] == 0xE9);
+}
+#endif
+
+#if EXT_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: IsExt
+//
+// Description:
+// Checks if given data block describes EXT Superblock structure
+//
+// Input:
+// VOLUME_SB *pSb - pointer to data block to check
+//
+// Output:
+// TRUE - data block is a EXT Superblock structure
+// FALSE - data block is not a EXT Superblock structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsExt(
+ IN VOLUME_SB *pSb )
+{
+ return pSb->SB_Magic == 0xEF53
+ && pSb->SB_BlockSize < 4
+ && pSb->SB_FirstBlock < 2
+ && pSb->SB_FreeBlocks < pSb->SB_TotalBlocks
+ && pSb->SB_FreeInodes < pSb->SB_TotalInodes;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetClustersCount
+//
+// Description:
+// Returns number of clusters for given cluster chain
+//
+// Input:
+// IN UINT8 FatType - FAT type (FAT12, FAT16 or FAT32)
+// IN UINT32 CurrentCluster - first cluster of cluster chain
+// UINT32 *NextCluster - first cluster of next cluster chain if there is break
+// IN BOOLEAN Continuous - if TRUE, returns only number of subsequent clusters in chain
+// if FALSE, returns total number of clusters in cluster chain
+//
+// Output:
+// UINT32 - number of clusters
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT32 GetClustersCount(
+ IN UINT8 FatType,
+ IN UINT32 CurrentCluster,
+ OUT UINT32 *NextCluster,
+ IN BOOLEAN Continuous )
+{
+ UINT32 Count = 0;
+ UINT32 WorkCluster;
+ UINT32 Cluster = CurrentCluster;
+
+ if ( FatType == FAT16 ) {
+ UINT16 *Fat16 = (UINT16*)FatBuffer;
+ while ( TRUE )
+ {
+ Count++;
+ WorkCluster = Fat16[Cluster];
+
+ if ( WorkCluster > 0xfff8 ) {
+ *NextCluster = 0;
+ break;
+ }
+
+ if ( WorkCluster != Cluster + 1 && Continuous ) {
+ *NextCluster = WorkCluster;
+ break;
+ }
+ Cluster = WorkCluster;
+ }
+ } else if ( FatType == FAT32 ) {
+ UINT32 *Fat32 = (UINT32*)FatBuffer;
+ while ( TRUE )
+ {
+ Count++;
+ WorkCluster = Fat32[Cluster] & 0xfffffff;
+
+ if ( WorkCluster > 0xffffff8 ) {
+ *NextCluster = 0;
+ break;
+ }
+
+ if ( WorkCluster != Cluster + 1 && Continuous ) {
+ *NextCluster = WorkCluster;
+ break;
+ }
+ Cluster = WorkCluster;
+ }
+ } else {
+ while ( TRUE ) {
+ Count++;
+ WorkCluster = *(UINT16*)(FatBuffer + Cluster + Cluster / 2);
+ WorkCluster = (Cluster & 1) ? WorkCluster >> 4 : WorkCluster & 0xfff;
+
+ if ( WorkCluster > 0xff8 ) {
+ *NextCluster = 0;
+ break;
+ }
+
+ if ( WorkCluster != Cluster + 1 && Continuous ) {
+ *NextCluster = WorkCluster;
+ break;
+ }
+ Cluster = WorkCluster;
+ }
+ }
+ return Count;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFatData
+//
+// Description:
+// Reads data from FAT device
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN RC_VOL_INFO *Volume - pointer to volume description structure
+// IN UINT32 FirstCluster - starting cluster
+// IN UINTN Size - size of the data to read
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_SUCCESS - correctly read all FAT data
+// EFI_ABORTED - should never get this.
+// Other - any errors reported from ReadDevice function
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetFatData(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN RC_VOL_INFO *Volume,
+ IN UINT32 FirstCluster,
+ IN UINTN Size,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ UINT32 Count;
+ UINT32 NextCluster;
+ UINT32 Cluster = FirstCluster;
+ UINTN SizeToRead;
+
+ while ( TRUE )
+ {
+ SizeToRead = Size;
+ Count = GetClustersCount( Volume->FatType, Cluster, &NextCluster, TRUE );
+ SizeToRead = (SizeToRead > Count * Volume->BytesPerCluster) ? Count * Volume->BytesPerCluster : SizeToRead;
+ Status = ReadDevice( PeiServices,
+ Volume,
+ Volume->DataOffset + Mul64((UINT64)(Cluster - 2), Volume->BytesPerCluster),
+ SizeToRead,
+ Buffer );
+
+ if ( EFI_ERROR( Status ) || NextCluster == 0 ) {
+ return Status;
+ }
+
+ Cluster = NextCluster;
+ (UINT8*)Buffer += SizeToRead;
+ Size -= SizeToRead;
+ }
+ return EFI_ABORTED; //should never get here
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFatType
+//
+// Description:
+// Prepares given volume for read operations. Reads FAT table, root directory,
+// determines FAT type
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN BOOT_SECTOR *Bs - pointer to MBR or diskette FAT data
+//
+// Output:
+// EFI_STATUS - possible return values from ReadDevice, AllocatePages, GetFatData
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetFatType(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN BOOT_SECTOR *Bs )
+{
+ EFI_STATUS Status;
+ UINT32 TotalSectors;
+ UINT32 FatSectors;
+ UINT32 RootSectors;
+ UINT32 DataSectors;
+ UINT32 RootSize;
+ UINT32 FatSize;
+ UINT32 DataClusters;
+ UINT32 RootClusters;
+ UINT32 DummyCluster;
+ UINTN FatPages;
+ UINTN RootPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ FatSectors = (Bs->FATSz16 != 0) ? Bs->FATSz16 : Bs->Fat.Fat32.FATSz32;
+ FatSize = FatSectors * Bs->BytsPerSec;
+ TotalSectors = (Bs->TotSec16 != 0) ? Bs->TotSec16 : Bs->TotSec32;
+ RootSectors = ((Bs->RootEntCnt * 32) + (Bs->BytsPerSec - 1)) / Bs->BytsPerSec;
+ RootSize = RootSectors * Bs->BytsPerSec;
+ DataSectors = TotalSectors - RootSectors - FatSectors * Bs->NumFATs - Bs->RsvdSecCnt;
+ DataClusters = DataSectors / Bs->SecPerClus;
+
+ Volume->FatOffset = Bs->RsvdSecCnt * Bs->BytsPerSec;
+ Volume->RootOffset = Volume->FatOffset + FatSectors * Bs->NumFATs * Bs->BytsPerSec;
+ Volume->DataOffset = Volume->RootOffset + RootSize;
+ Volume->BytesPerCluster = Bs->BytsPerSec * Bs->SecPerClus;
+ Volume->FatType = (DataClusters >= 65525) ? FAT32 : ((DataClusters < 4085) ? FAT12 : FAT16);
+
+ RootEntries = Bs->RootEntCnt;
+
+ //
+ //Read FAT table
+ //
+ FatPages = EFI_SIZE_TO_PAGES( FatSize );
+
+ if ( FatBufferSize < EFI_PAGES_TO_SIZE( FatPages )) {
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, FatPages, &Allocate );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ FatBuffer = (UINT8*)((UINTN)Allocate);
+ FatBufferSize = EFI_PAGES_TO_SIZE( FatPages );
+ }
+ MemSet( FatBuffer, FatBufferSize, 0 );
+ Status = ReadDevice( PeiServices, Volume, Volume->FatOffset, FatSize, FatBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ //Read Root directory
+ //
+ if ( RootSize == 0 ) {
+ //
+ //in case of FAT32 it will be so at this time
+ //
+ RootClusters = GetClustersCount( FAT32, Bs->Fat.Fat32.RootClus, &DummyCluster, FALSE );
+ RootSize = RootClusters * Volume->BytesPerCluster;
+ RootEntries = RootSize / 32;
+ }
+
+ RootPages = EFI_SIZE_TO_PAGES( RootSize );
+
+ if ( RootBufferSize < EFI_PAGES_TO_SIZE( RootPages )) {
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, RootPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ RootBuffer = (UINT8*)((UINTN)Allocate);
+ RootBufferSize = EFI_PAGES_TO_SIZE( RootPages );
+ }
+ MemSet( RootBuffer, RootBufferSize, 0 );
+
+ if ( Volume->FatType == FAT32 ) {
+ Status = GetFatData( PeiServices, Volume, Bs->Fat.Fat32.RootClus, RootSize, RootBuffer );
+ }
+ else {
+ Status = ReadDevice( PeiServices, Volume, Volume->RootOffset, RootSize, RootBuffer );
+ }
+
+ return Status;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessFatVolume
+//
+// Description:
+// Reads recovery capsule from FAT volume
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessFatVolume(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+// BOOT_SECTOR Bs;
+ UINT32 i;
+ UINT32 FirstFileCluster;
+ UINTN NumberOfFiles;
+
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Bs );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if (!IsFat( &MemBlk->Bs )) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetFatType( PeiServices, Volume, &MemBlk->Bs );
+#if SEARCH_FAT_PATH
+ ThisVolume = Volume; // Save volume info for path search
+#endif
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ GetFileListFromFatVolume((DIR_ENTRY*)RootBuffer, RootEntries, &NumberOfFiles, FatRecoveryFiles);
+ //
+ if ( NumberOfFiles == 0 )
+ return EFI_NOT_FOUND;
+
+ for(i = 0; i < NumberOfFiles; i++) {
+ if ( *FileSize < FatRecoveryFiles[i]->FileSize )
+ continue;
+
+ FirstFileCluster = (FatRecoveryFiles[i]->FirstClusterHi << 16) + FatRecoveryFiles[i]->FirstClusterLo;
+
+ Status = GetFatData( PeiServices, Volume, FirstFileCluster, FatRecoveryFiles[i]->FileSize, Buffer );
+ if(EFI_ERROR(Status))
+ continue;
+
+ if(IsValidFile(Buffer, FatRecoveryFiles[i]->FileSize)) {
+ *FileSize = FatRecoveryFiles[i]->FileSize;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+#if NTFS_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetRunListElementData
+//
+// Description: (NTFS) Retrieves the count and cluster of a run from a run list element
+//
+// Parameters: UINT8 **pRunList - Pointer to the run list, updated if
+// UpdateList is TRUE.
+// UINT64 *ClusterCount - Length of this run in clusters.
+// UINT64 *Cluster - Starting cluster of this run.
+// BOOLEAN UpdateList - Update list pointer to next element if TRUE.
+//
+// Return value: EFI_STATUS Status (EFI_SUCCESS or EFI_END_OF_FILE)
+//
+// Modified:
+//
+// Referral(s):
+//
+// NOTE(S): A run list element has 3 parts -- a size byte, a Cluster
+// count, and a Cluster Number.
+// The low nibble of the size byte is the size of the Count
+// in bytes. The high nibble is the size of the Offset in
+// bytes. The element is therefore 1 + (low nibble) + (high
+// nibble) bytes long.
+// The cluster number is a signed number. The new cluster is
+// added to the old one to get the result. So if the new
+// cluster lies before the old one on the disk, it will be
+// a negative number.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetRunListElementData (
+ UINT8 **pRunList,
+ UINT64 *ClusterCount,
+ UINT64 *Cluster,
+ BOOLEAN UpdateList
+ )
+{
+ UINT64 TempCount = 0;
+ UINT64 TempCluster = 0;
+ UINT64 LeftFill = 0;
+ UINT8 LowNibble;
+ UINT8 HighNibble;
+ UINT8 i, HighByte;
+ UINT8 *RunListPtr;
+
+//
+// If the size byte is 0, we have reached the end of the file.
+//
+ RunListPtr = *pRunList;
+ if (RunListPtr[0] == 0)
+ {
+ return EFI_END_OF_FILE;
+ }
+
+ LowNibble = RunListPtr[0] & 0xF;
+ HighNibble = RunListPtr[0] >> 4;
+ RunListPtr++;
+//
+// Get run length.
+//
+ for (i=LowNibble; i>0; i--)
+ {
+ TempCount = Shl64(TempCount, 8);
+ TempCount += RunListPtr[i-1];
+ }
+ RunListPtr += LowNibble;
+//
+// Get the run offset.
+//
+ HighByte = RunListPtr[HighNibble-1];
+ for (i=HighNibble; i>0; i--)
+ {
+ TempCluster = Shl64(TempCluster, 8);
+ TempCluster += RunListPtr[i-1];
+ }
+ RunListPtr += HighNibble;
+//
+// If the offset is negative, left-fill the empty bytes with 0xFF.
+//
+ if ((HighByte & 0x80) && (HighNibble < 8))
+ {
+ for (i=8; i>HighNibble; i--)
+ {
+ LeftFill = Shr64(LeftFill, 8);
+ LeftFill |= 0xFF00000000000000;
+ }
+ TempCluster |= LeftFill;
+ }
+
+ *Cluster += TempCluster;
+ *ClusterCount = TempCount;
+ if (UpdateList) *pRunList = RunListPtr;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFrAttribute
+//
+// Description: (NTFS) Retrieves a File Record Attribute by it's number from a
+// File Record.
+//
+// Parameters: UINT8 *BufferIn - Pointer to a buffer containing a file record
+// UINT8 AttributeNumber - Number of the attribute to retrieve
+// UINTN **BufferOut - Points to the attribute in the buffer
+//
+// Return value: EFI_STATUS Status (EFI_SUCCESS or EFI_NOT_FOUND)
+//
+// Modified:
+//
+// Referral(s):
+//
+// Note(s): Attributes are in sequential order, so, for example,
+// if we're looking for 30, and we find 10 and then 40,
+// we know there is no 30 in the record.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+GetFrAttribute (
+ UINT8 *BufferIn,
+ UINT8 AttributeNumber,
+ UINT8 **BufferOut
+ )
+{
+ UINT8 *TempBuffer;
+
+ TempBuffer = BufferIn;
+
+//
+// Point to 1st attribute.
+//
+ TempBuffer += ((MFT_FILE_RECORD*)TempBuffer)->FR_AttributeOffset;
+//
+// Search for the attribute.
+//
+ while (TempBuffer[0] != AttributeNumber)
+ {
+ if (TempBuffer[0] > AttributeNumber) return EFI_NOT_FOUND;
+ if (TempBuffer[0] == 0xFF) return EFI_NOT_FOUND;
+ if ( ((FR_ATTR_HEADER_RES*)TempBuffer)->AHR_Length == 0 )
+ return EFI_NOT_FOUND;
+ TempBuffer += ((FR_ATTR_HEADER_RES*)TempBuffer)->AHR_Length;
+ }
+
+ *BufferOut = TempBuffer;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFileRecord
+//
+// Description: (NTFS) Returns the file record specified by MFTRecordNo in a buffer.
+//
+// Parameters: VOLUME_INFO *Vi - Volume Info Structure
+// BOOT_SECTOR *Bs - Boot sector structure
+// UINT64 MFTRecordNo - MFT Record number to get
+// UINT8 *Buffer - Buffer to read record into
+// UINT64 *MFTSector - Sector where record found
+//
+// Return value: EFI_STATUS Status (EFI_SUCCESS or EFI_NOT_FOUND)
+//
+// Modified:
+//
+// Referral(s):
+//
+// NOTE(S): The File Records in the Master File Table are numbered
+// sequentially. We just have to count our way through the
+// MFT's run list until we find it.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS
+GetFileRecord (
+ EFI_PEI_SERVICES **PeiServices,
+ RC_VOL_INFO *Volume,
+ BOOT_SECTOR *Bs,
+ UINT64 MFTRecordNo,
+ UINT8 *FrBuffer,
+ UINT64 *MFTSector OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *pRunList;
+ UINT64 Cluster;
+ UINT64 Sector;
+ UINT64 Count;
+ UINT64 ByteCount;
+ UINT32 SecPerRecord = 1;
+ UINT64 RecordCount;
+ UINT32 BytesPerCluster;
+ UINT64 Offset;
+ UINT32 RecordSize;
+
+ Cluster = 0;
+ pRunList = &MemBlk->MFTRunList[0];
+
+ MFTRecordNo &= MAXIMUM_RECORD_NUMBER; // Isolate number part
+
+ Status = GetRunListElementData(&pRunList, &Count, &Cluster, TRUE);
+ BytesPerCluster = Bs->BytsPerSec * Bs->SecPerClus;
+ ByteCount = Mul64(Count, BytesPerCluster);
+ if ( Bs->BytsPerSec <= FILE_RECORD_SIZE ) {
+ SecPerRecord = FILE_RECORD_SIZE / Bs->BytsPerSec;
+ RecordSize = FILE_RECORD_SIZE;
+ } else { // Special case for 4k sectors
+ SecPerRecord = 1;
+ RecordSize = (UINT32)Bs->BytsPerSec;
+ }
+//###DEBUG CHANGE NEEDED LATER ////
+// In NTFS, the cluster size can be 512 bytes to 4096 bytes.
+// File records are 1024 bytes
+// For now, we're going to assume a cluster size of 1024 bytes or more.
+////////////////////////////
+
+ Sector = Mul64(Cluster, Bs->SecPerClus);
+ RecordCount = 0;
+ do {
+ if (ByteCount > 0)
+ {
+ Sector += SecPerRecord;
+ ByteCount -= RecordSize;
+ } else { // We've used up a run, read from the next one.
+ Status = GetRunListElementData(&pRunList, &Count, &Cluster, TRUE);
+ if (EFI_ERROR(Status)) return EFI_NOT_FOUND;
+ ByteCount = Mul64(Count, BytesPerCluster);
+ Sector = Mul64(Cluster, Bs->SecPerClus);
+ continue;
+ }
+ RecordCount++;
+ } while (RecordCount < MFTRecordNo); // Record numbers are 0-based.
+//
+// We found the sector of the file record wanted. Now read it.
+//
+ Offset = Mul64( Sector, Bs->BytsPerSec );
+ Status = ReadDevice( PeiServices, Volume, Offset, RecordSize, FrBuffer );
+ if (EFI_ERROR(Status)) return EFI_NOT_FOUND;
+//
+// A File recored begins with "FILE". Check it.
+//
+ if ( (FrBuffer[0] != 0x46) || \
+ (FrBuffer[1] != 0x49) || \
+ (FrBuffer[2] != 0x4C) || \
+ (FrBuffer[3] != 0x45) ) return EFI_NOT_FOUND;
+
+ *MFTSector = Sector; // Return sector where the record was found
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadNTFSFile
+//
+// Description:
+// Reads a file from a device formatted in NTFS.
+//
+// Input:
+// Parameters: VOLUME_INFO *Vi - Volume Info Structure
+// BOOT_SECTOR *Bs - Boot sector structure
+// UINT8 *RunList - Run List of file to read
+// VIOD *Buffer - Buffer to read into
+// UINT64 *Size - Size of file to read
+//
+// Output:
+// EFI_STATUS - possible return values
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadNTFSFile(
+ IN EFI_PEI_SERVICES **PeiServices,
+ RC_VOL_INFO *Volume,
+ BOOT_SECTOR *Bs,
+ UINT8 *RunList,
+ VOID *Buffer,
+ UINT64 *Size )
+{
+ UINT64 TotalContiguousBytes;
+ UINT64 TotalBytesRead = 0;
+ UINT64 AbsByte;
+ UINT64 AccessBytes;
+ UINT64 ClusterCount;
+ UINT64 Cluster = 0;
+ EFI_STATUS Status;
+
+ Status = GetRunListElementData(&RunList, &ClusterCount,
+ &Cluster, TRUE);
+ do {
+ TotalContiguousBytes = Mul64(ClusterCount,
+ Bs->SecPerClus);
+ TotalContiguousBytes = Mul64(TotalContiguousBytes,
+ Bs->BytsPerSec);
+ if ( TotalContiguousBytes > *Size) AccessBytes = *Size;
+
+ else AccessBytes = TotalContiguousBytes;
+
+ AbsByte = Mul64( Cluster, Bs->SecPerClus );
+ AbsByte = Mul64( AbsByte, Bs->BytsPerSec );
+
+ if (AccessBytes == 0) {
+ return EFI_VOLUME_CORRUPTED; // Will happen if early EOF.
+ }
+
+ Status = ReadDevice( PeiServices,
+ Volume,
+ AbsByte,
+ (UINTN)AccessBytes,
+ Buffer );
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ (UINT8 *)Buffer += AccessBytes;
+ TotalBytesRead +=AccessBytes;
+
+ *Size -= AccessBytes;
+
+ if (AccessBytes == TotalContiguousBytes)
+ {
+ Status = GetRunListElementData (&RunList, &ClusterCount,
+ &Cluster, TRUE);
+ if (EFI_ERROR(Status)) break; // Error here means EOF.
+ }
+
+ } while (*Size);
+
+ *Size = (UINT32)TotalBytesRead;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadNTFSRoot
+//
+// Description:
+// Prepares given volume for read operations. Reads NTFS root directory.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN BOOT_SECTOR *Bs - pointer to MBR
+//
+// Output:
+// EFI_STATUS - possible return values
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadNTFSRoot(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN BOOT_SECTOR *Bs )
+{
+ UINT8 FrBuffer[FILE_RECORD_SIZE]; // This needs to be 4096 for 4k secs.
+ UINT8 *Buffer2;
+ UINT8 *Buffer3;
+ UINT8 *pRunList;
+ EFI_STATUS Status;
+ UINT64 TotalSectors;
+ UINT64 DataSectors;
+ UINT64 Temp64;
+ UINT32 Temp32;
+ UINT16 Temp16;
+ UINT32 IndexSize;
+ UINT64 Cluster = 0;
+ UINT64 ClusterCount;
+ UINT64 TmpRootSize;
+ UINTN RootPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ TotalSectors = Bs->Fat.Ntfs.TotSec64;
+ DataSectors = TotalSectors - Bs->RsvdSecCnt;
+
+ Temp64 = Mul64( Bs->Fat.Ntfs.MFTClus, Bs->SecPerClus );
+ Volume->FatOffset = Mul64( Temp64, Bs->BytsPerSec ); // For NTFS, FatOffset is MFT Offset
+
+ //
+ // Read the first file record of the MFT, to get the MFT run list.
+ //
+ Status = ReadDevice( PeiServices, Volume, Volume->FatOffset, FILE_RECORD_SIZE, FrBuffer );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Buffer2 = &FrBuffer[0];
+ Status = GetFrAttribute( Buffer2, FR_ATTRIBUTE_DATA, &Buffer2 ); // Get data attribute
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Buffer2 += ((FR_ATTR_HEADER_NONRES*)Buffer2)->AHNR_RunOffset; // Point to run list
+ MemCpy( MemBlk->MFTRunList, Buffer2, 256 ); // Copy MFT run list
+ //
+ // Get the root directory file record, to get its run list.
+ //
+ Buffer2 = &FrBuffer[0];
+ Status = GetFileRecord( PeiServices, Volume, Bs, 5, Buffer2, NULL ); // Root is always record no. 5
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ //
+ // Check for a resident index. It will be in the Index Root Attribute.
+ // If one if found, it will be saved for searching later.
+ //
+ ResidentPresent = FALSE;
+ Buffer3 = Buffer2;
+ Status = GetFrAttribute( Buffer2, FR_ATTRIBUTE_INDEX_ROOT, &Buffer3 );
+ if ( Status == EFI_SUCCESS) { // Root Attribute found
+ Temp16 = ((FR_ATTR_HEADER_RES*)Buffer3)->AHR_InfoOffset;
+ Buffer3 += Temp16;
+ IndexSize = ((FR_INDEX_ROOT_ATTRIBUTE*)Buffer3)->IRA_TotalSize;
+ Temp32 = ((FR_INDEX_ROOT_ATTRIBUTE*)Buffer3)->IRA_Offset;
+ Buffer3 += Temp32 + EFI_FIELD_OFFSET(FR_INDEX_ROOT_ATTRIBUTE, IRA_Offset);
+ if (IndexSize >= MINIMUM_ENTRY_SIZE) { // Resident index is not empty
+ MemCpy ( MemBlk->ResidentIndex, Buffer3, IndexSize );
+ ResidentPresent = TRUE;
+ ResidentSize = IndexSize;
+ }
+ }
+ //
+ // Now, check for a non-resident index.
+ //
+ Status = GetFrAttribute( Buffer2, FR_ATTRIBUTE_INDEX_ALLOC, &Buffer2 );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Buffer2 += ((FR_ATTR_HEADER_NONRES*)Buffer2)->AHNR_RunOffset; // Point to run list
+ MemCpy( MemBlk->RootRunList, Buffer2, 128 ); // Copy Root run list
+ //
+ // Calculate root directory size by running its run list.
+ //
+ pRunList = &MemBlk->RootRunList[0];
+ TmpRootSize = 0;
+ Cluster = 0;
+ do {
+ Status = GetRunListElementData( &pRunList, &ClusterCount, &Cluster, TRUE );
+ if ( Status == EFI_SUCCESS ) TmpRootSize += ClusterCount;
+ } while ( Status == EFI_SUCCESS );
+ TmpRootSize = Mul64 ( TmpRootSize, Bs->SecPerClus );
+ TmpRootSize = Mul64 ( TmpRootSize, Bs->BytsPerSec );
+
+ Buffer2 = &FrBuffer[0];
+ RootPages = EFI_SIZE_TO_PAGES( TmpRootSize );
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, RootPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ RootBuffer = (UINT8*)((UINTN)Allocate);
+ RootBufferSize = EFI_PAGES_TO_SIZE( RootPages );
+ MemSet( RootBuffer, RootBufferSize, 0 );
+
+ pRunList = &MemBlk->RootRunList[0];
+ Status = ReadNTFSFile( PeiServices, Volume, Bs, pRunList, RootBuffer, &TmpRootSize );
+ RootSize = (UINT32)TmpRootSize;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessNTFSVolume
+//
+// Description:
+// Reads recovery capsule from NTFS volume
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessNTFSVolume(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+// BOOT_SECTOR Bs;
+ UINT32 i;
+ UINTN NumberOfFiles;
+ UINT64 MFTRecord;
+ UINT8 *TmpBuffer;
+ UINT8 *pRunList;
+ UINT64 TmpFileSize;
+
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Bs );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if (!IsNtfs( &MemBlk->Bs )) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ReadNTFSRoot( PeiServices, Volume, &MemBlk->Bs );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ GetFileListFromNtfsVolume((UINT8*)RootBuffer, RootSize, &NumberOfFiles, NtfsRecoveryFiles);
+
+ if ( NumberOfFiles == 0 )
+ return EFI_NOT_FOUND;
+
+ for(i = 0; i < NumberOfFiles; i++) {
+ if ( *FileSize < NtfsRecoveryFiles[i]->INDE_RealSize )
+ continue;
+
+ TmpBuffer = (UINT8*)Buffer;
+ TmpFileSize = NtfsRecoveryFiles[i]->INDE_RealSize;
+ //
+ // Get the file's MFT record number, and from that it's run list
+ //
+ MFTRecord = NtfsRecoveryFiles[i]->INDE_MFTRecord & MAXIMUM_RECORD_NUMBER;
+ Status = GetFileRecord( PeiServices, Volume, &MemBlk->Bs, MFTRecord, TmpBuffer, NULL );
+ Status = GetFrAttribute( TmpBuffer, FR_ATTRIBUTE_DATA, &TmpBuffer );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ TmpBuffer += ((FR_ATTR_HEADER_NONRES*)TmpBuffer)->AHNR_RunOffset; // Point to run list
+ MemCpy( MemBlk->RootRunList, TmpBuffer, 128 ); // Copy the file's run list
+ //
+ // Read the file into the provided buffer
+ //
+ pRunList = &MemBlk->RootRunList[0];
+ Status = ReadNTFSFile( PeiServices, Volume, &MemBlk->Bs, pRunList, Buffer, &TmpFileSize );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if(IsValidFile(Buffer, (UINTN)TmpFileSize)) {
+ *FileSize = (UINTN)TmpFileSize;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+#endif
+
+#if EXT_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetNextBlock
+//
+// Description: (EXT) Retrieves the next block number from an Inode
+// block list.
+//
+// Parameters: VOLUME_INFO *Vi - Volume Info Structure
+// VOLUME_SB *Sb - Superblock structure
+// VOLUME_IT *Inode - Inode table structure
+// UINT32 *BlockNo - Sequential number of the block
+// UINT32 *Block - Next block of the file
+// BOOLEAN UpdateList - Update block no. to next block if TRUE.
+//
+// Return value: EFI_STATUS Status (EFI_SUCCESS or EFI_END_OF_FILE)
+//
+// Modified:
+//
+// Referral(s):
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetNextBlock(
+ EFI_PEI_SERVICES **PeiServices,
+ RC_VOL_INFO *Volume,
+ VOLUME_SB *Sb,
+ VOLUME_IT *Inode,
+ UINT32 *BlockNo,
+ UINT32 *Block,
+ BOOLEAN UpdateList )
+{
+ UINT32 *BlockListPtr;
+ UINT32 TmpBlock;
+ UINT32 TmpBlock2;
+ UINT32 TmpBlkNo;
+ UINT32 IBlkCnt;
+ UINT64 Offset;
+ UINT32 BlockSize;
+ UINT32 NosPerBlock;
+ UINTN BlockPages;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ BlockSize = 1024 << Sb->SB_BlockSize;
+ NosPerBlock = BlockSize / 4;
+ TmpBlkNo = *BlockNo;
+
+ // Process direct blocks (0-11)
+ if ((TmpBlkNo < 12) && (Indirect == 0))
+ {
+ BlockListPtr = &Inode->Alloc.Ext2.Blocks[0];
+ *Block = BlockListPtr[TmpBlkNo];
+ }
+
+ // Process single indirect blocks (12-(256+11))
+ if ((TmpBlkNo >= 12) && (TmpBlkNo < NosPerBlock+12) && (Indirect != 1))
+ {
+ Indirect = 1;
+ TmpBlock = Inode->Alloc.Ext2.Blocks[12];
+ Offset = Mul64(TmpBlock, BlockSize);
+ ReadDevice (PeiServices, Volume, Offset, BlockSize, &BlockList[0]);
+ }
+
+ if ((TmpBlkNo >= 12) && (TmpBlkNo < NosPerBlock+12) && (Indirect == 1))
+ {
+ BlockPages = EFI_SIZE_TO_PAGES( BlockSize );
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, BlockPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return EFI_END_OF_FILE;
+ }
+ BlockList = (UINT32*)((UINTN)Allocate);
+
+ BlockListPtr = &BlockList[0];
+ TmpBlock = TmpBlkNo - 12;
+ *Block = BlockListPtr[TmpBlock];
+ }
+
+ // Process double indirect blocks ((256+12)-(65536+256+11))
+ if ((TmpBlkNo >= (NosPerBlock+12)) && (Indirect != 2))
+ {
+ Indirect = 2;
+ BlockPages = EFI_SIZE_TO_PAGES( BlockSize );
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, BlockPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return EFI_END_OF_FILE;
+ }
+ BlockList2 = (UINT32*)((UINTN)Allocate);
+
+ TmpBlock = Inode->Alloc.Ext2.Blocks[13];
+ Offset = Mul64(TmpBlock, BlockSize);
+ ReadDevice (PeiServices, Volume, Offset, BlockSize, &BlockList[0]);
+ }
+
+ if ((TmpBlkNo >= (NosPerBlock+12)) && (Indirect == 2))
+ {
+ TmpBlock = TmpBlkNo - 12;
+ IBlkCnt = TmpBlock / NosPerBlock;
+ if (TmpBlock % NosPerBlock == 0)
+ {
+ // Read another set of nos. into BlockList2
+ TmpBlock2 = BlockList[IBlkCnt];
+ Offset = Mul64(TmpBlock2, BlockSize);
+ ReadDevice (PeiServices, Volume, Offset, BlockSize, &BlockList2[0]);
+ BlockListPtr = &BlockList2[0];
+ }
+ TmpBlock -= (NosPerBlock * IBlkCnt);
+ *Block = BlockListPtr[TmpBlock];
+ }
+
+ if (UpdateList)
+ {
+ TmpBlkNo++;
+ *BlockNo = TmpBlkNo;
+ }
+ if (*Block == 0)
+ {
+ return EFI_END_OF_FILE;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadExtFile
+//
+// Description:
+// Reads a file from a device formatted in Ext(n).
+//
+// Input:
+// Parameters: VOLUME_INFO *Vi - Volume Info Structure
+// VOLUME_SB *Sb - Superblock structure
+// VOLUME_IT *Inode - Inode table structure
+// VIOD *Buffer - Buffer to read into
+// UINT64 *Size - Size of file to read
+//
+// Output:
+// EFI_STATUS - possible return values
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadExtFile(
+ IN EFI_PEI_SERVICES **PeiServices,
+ RC_VOL_INFO *Volume,
+ VOLUME_SB *Sb,
+ VOLUME_IT *Inode,
+ VOID *Buffer,
+ UINT64 *Size )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ UINT32 Block;
+ UINT32 BlockNo;
+ UINT64 Offset;
+ UINT64 TotalBytesRead = 0;
+ UINT16 ExtentCount;
+ UINT64 BigBlock;
+ UINT32 ReadSize;
+ UINT16 i;
+
+ BlockSize = 1024 << Sb->SB_BlockSize;
+ BlockNo = 0;
+
+ //
+ // Check for which allocation method to use for reading the file
+ //
+ if ((Inode->Alloc.Ext4.Header.EH_Magic == 0xF30A) && \
+ (Inode->Alloc.Ext4.Header.EH_Max == 4))
+ {
+ //
+ // Use the EXT4 allocation method
+ //
+ ExtentCount = Inode->Alloc.Ext4.Header.EH_Extents;
+
+ for (i=0; i<ExtentCount; i++)
+ {
+ BigBlock = Inode->Alloc.Ext4.Extent[i].EE_BlockLo + \
+ Shl64(Inode->Alloc.Ext4.Extent[i].EE_BlockHi, 0x20);
+ Offset = Mul64(BigBlock, BlockSize);
+ ReadSize = BlockSize * Inode->Alloc.Ext4.Extent[i].EE_Length;
+ if (*Size <= ReadSize)
+ {
+ Status = ReadDevice (PeiServices, Volume, Offset, (UINTN)*Size, Buffer);
+ if (EFI_ERROR(Status)) {
+ *Size = TotalBytesRead;
+ return Status;
+ } else {
+ TotalBytesRead += *Size;
+ *Size = TotalBytesRead;
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ReadDevice (PeiServices, Volume, Offset, ReadSize, Buffer);
+ if (EFI_ERROR(Status)) return Status;
+ *Size -= ReadSize;
+ TotalBytesRead += ReadSize;
+ } // End of read loop
+
+ return EFI_VOLUME_CORRUPTED; // Shouldn't get here
+
+ } else {
+ //
+ // Use the EXT2, EXT3 allocation method
+ //
+ Status = GetNextBlock ( PeiServices,
+ Volume,
+ Sb,
+ Inode,
+ &BlockNo,
+ &Block,
+ TRUE );
+ if (EFI_ERROR(Status)) // Zero-length file
+ {
+ *Size = 0;
+ return Status;
+ }
+
+ do
+ {
+ Offset = Mul64 (BlockSize, Block);
+
+ if (*Size <= BlockSize)
+ {
+ Status = ReadDevice (PeiServices, Volume, Offset, (UINTN)*Size, Buffer);
+ if (EFI_ERROR(Status)) {
+ *Size = TotalBytesRead;
+ return Status;
+ } else {
+ TotalBytesRead += *Size;
+ *Size = TotalBytesRead;
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ReadDevice (PeiServices, Volume, Offset, BlockSize, Buffer);
+ if (EFI_ERROR(Status)) return Status;
+ *Size -= BlockSize;
+ TotalBytesRead += BlockSize;
+
+ Status = GetNextBlock ( PeiServices,
+ Volume,
+ Sb,
+ Inode,
+ &BlockNo,
+ &Block,
+ TRUE );
+ if (EFI_ERROR(Status)) // EOF found
+ {
+ *Size = TotalBytesRead;
+ return EFI_SUCCESS;
+ }
+ }
+ while (*Size);
+
+ return EFI_VOLUME_CORRUPTED; // Shouldn't get here
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReadExtRoot
+//
+// Description:
+// Prepares given volume for read operations. Reads Ext(n) root directory.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN VOLUME_SB *Sb - pointer to Superblock
+//
+// Output:
+// EFI_STATUS - possible return values
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadExtRoot(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN VOLUME_SB *Sb )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ UINT16 InodeSize;
+ UINT32 BgdtBlock;
+ VOLUME_BGDT Bgdt;
+// VOLUME_IT RootInode;
+ UINT64 Offset;
+ UINT64 TmpRootSize;
+ UINTN RootPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ BlockSize = 1024 << Sb->SB_BlockSize;
+ if (BlockSize == 1024)
+ {
+ BgdtBlock = 2;
+ } else {
+ BgdtBlock = 1;
+ }
+
+ // Read in the Block Group Descriptor Table
+ Offset = Mul64(BlockSize, BgdtBlock);
+ Status = ReadDevice (PeiServices,
+ Volume,
+ Offset,
+ sizeof(VOLUME_BGDT),
+ &Bgdt);
+ if (EFI_ERROR(Status))
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ InodeBlock = Bgdt.BGDT_InodeTableBlk;
+ InodeSize = Sb->SB_InodeStrucSize;
+
+ // The root directory's inode is always the 2nd inode in the
+ // inode table. Read in that inode.
+ Offset = Mul64(BlockSize, InodeBlock) + InodeSize;
+ Status = ReadDevice (PeiServices,
+ Volume,
+ Offset,
+ sizeof(VOLUME_IT),
+ &MemBlk->RootInode);
+ if (EFI_ERROR(Status))
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ TmpRootSize = MemBlk->RootInode.IT_SizeLo + Shl64(MemBlk->RootInode.IT_SizeHi, 0x20);
+
+ RootPages = EFI_SIZE_TO_PAGES( TmpRootSize );
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, RootPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ RootBuffer = (UINT8*)((UINTN)Allocate);
+ RootBufferSize = EFI_PAGES_TO_SIZE( RootPages );
+ MemSet( RootBuffer, RootBufferSize, 0 );
+
+ Status = ReadExtFile( PeiServices,
+ Volume,
+ Sb,
+ &MemBlk->RootInode,
+ RootBuffer,
+ &TmpRootSize );
+ RootSize = (UINT32)TmpRootSize;
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessExtVolume
+//
+// Description:
+// Reads recovery capsule from Ext(n) volume
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output: EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessExtVolume(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+// VOLUME_SB Sb;
+// VOLUME_IT FileInode;
+ UINT32 i;
+ UINT32 Inode;
+ UINT64 TmpFileSize;
+ UINTN NumberOfFiles;
+ UINT64 Offset;
+ UINT32 BlockSize;
+ UINT16 InodeSize;
+ UINT8 *TmpPtr;
+
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Sb );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ // On an EXT(n) volume, the first sector will be all zeros
+ TmpPtr = (UINT8*)&MemBlk->Sb.SB_TotalInodes;
+ for (i=0; i<512; i++)
+ {
+ if ((UINT8)TmpPtr[i] != 0)
+ {
+ return EFI_NOT_FOUND; // Not an EXT(n) volume
+ }
+ }
+
+ // The Superblock is always 1024 bytes in on the volume
+ Status = ReadDevice( PeiServices, Volume, 1024, 512, &MemBlk->Sb );
+
+ if (!IsExt( &MemBlk->Sb )) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ReadExtRoot( PeiServices, Volume, &MemBlk->Sb );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ GetFileListFromExtVolume((UINT8*)RootBuffer, RootSize, &NumberOfFiles, ExtRecoveryFiles);
+
+ if ( NumberOfFiles == 0 )
+ return EFI_NOT_FOUND;
+
+ BlockSize = 1024 << MemBlk->Sb.SB_BlockSize;
+ InodeSize = MemBlk->Sb.SB_InodeStrucSize;
+ for(i = 0; i < NumberOfFiles; i++) {
+ // An EXT(n) directory entry only contains the name and inode, so we have to
+ // read the inode to get the size.
+ Inode = ExtRecoveryFiles[i]->DIR_Inode;
+ Offset = Mul64(BlockSize, InodeBlock) + \
+ Mul64((Inode-1), InodeSize);
+ Status = ReadDevice (PeiServices,
+ Volume,
+ Offset,
+ sizeof(VOLUME_IT),
+ &MemBlk->FileInode);
+ if (EFI_ERROR(Status)) continue;
+
+ TmpFileSize = MemBlk->FileInode.IT_SizeLo + Shl64(MemBlk->FileInode.IT_SizeHi, 0x20);
+ if ( *FileSize < (UINTN)TmpFileSize )
+ continue;
+ Status = ReadExtFile( PeiServices,
+ Volume,
+ &MemBlk->Sb,
+ &MemBlk->FileInode,
+ Buffer,
+ &TmpFileSize );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if(IsValidFile(Buffer, (UINTN)TmpFileSize)) {
+ *FileSize = (UINTN)TmpFileSize;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindNextPartition
+//
+// Description:
+// Finds the next partition on the volume, and sets the VolumeOffset in
+// the RC_VOL_INFO structure.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+//
+// Output:
+// EFI_STATUS
+//
+// Note:
+// This function uses the following global variables:
+// UINTN PartCount - Counter to keep track of search
+// BOOLEAN IsMbr - True if looking for MBR partitions
+// UINT32 GpeCount - GUID Partition Entry count
+// UINT32 PartSector - Starting sector of partition
+// PartCount and PartSector must be seeded to 0, and IsMbr must be
+// seeded to TRUE before the first call.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindNextPartition(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume )
+{
+ EFI_STATUS Status;
+ UINT64 Offset;
+ GUID_BOOT_RECORD *Gbr;
+ GUID_TABLE_HEADER *Gth;
+ UINT32 GpeSize;
+ UINT32 i;
+ UINT32 TempSector;
+
+ //
+ // Check for MBR partitions
+ //
+ if ( IsMbr ) {
+ while ( PartCount < 4 ) {
+ if ( MemBlk->Mbr.PartRec[PartCount].OSType == 0xEE ) {
+ IsMbr = FALSE; // Mark GUID partition found
+ PartCount = 0; // Reset counter
+ break;
+ }
+
+ if ( MemBlk->Mbr.PartRec[PartCount].OSType == 5
+ || MemBlk->Mbr.PartRec[PartCount].OSType == 15 ) { // Extended partition
+ PartSector += MemBlk->Mbr.PartRec[PartCount].StartingLba;
+ Volume->PartitionOffset = Mul64( 512, PartSector );
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Mbr );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ PartCount = 0;
+ }
+
+ if ( MemBlk->Mbr.PartRec[PartCount].OSType == 0
+ || MemBlk->Mbr.PartRec[PartCount].SizeInLba == 0
+ || MemBlk->Mbr.PartRec[PartCount].StartingLba == 0 ) {
+ PartCount++; // Check next partition
+ continue;
+ }
+
+ TempSector = MemBlk->Mbr.PartRec[PartCount].StartingLba + PartSector;
+ Volume->PartitionOffset = Mul64( 512, TempSector );
+ PartCount++;
+ return EFI_SUCCESS;
+ }
+ }
+ if ( IsMbr ) return EFI_NOT_FOUND; // No MBR partitions were found
+
+ //
+ // Check for GUID partitions
+ //
+ if ( PartCount == 0 ) {
+ Offset = Mul64( 1, Volume->BlockSize );
+ Status = ReadDevice( PeiServices, Volume, Offset, 512, &MemBlk->Mbr );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ Gth = (GUID_TABLE_HEADER*)&MemBlk->Mbr.BootCode[0];
+ if ( (Gth->Signature[0] == 0x45) && // Check for "EFI"
+ (Gth->Signature[1] == 0x46) &&
+ (Gth->Signature[2] == 0x49) )
+ {
+ GpeCount = Gth->EntryCount;
+ GpeSize = Gth->EntrySize;
+ //
+ // We only support entry size of 128 for now.
+ //
+ if ( GpeSize != 128 ) return EFI_NOT_FOUND; //
+ Offset = Mul64( 2, Volume->BlockSize );
+ //
+ // Read in the first entry in the partition table
+ //
+ Status = ReadDevice( PeiServices, Volume, Offset, 512, &MemBlk->Mbr );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ } else return EFI_NOT_FOUND; // Table header not found.
+ }
+
+ while ( PartCount < GpeCount ) {
+ i = PartCount % 4;
+ if ( (i == 0) && (PartCount != 0) ) {
+ Offset = Mul64( 2+(PartCount/4), Volume->BlockSize );
+ Volume->PartitionOffset = 0; // Reset this to zero
+ Status = ReadDevice( PeiServices, Volume, Offset, 512, &MemBlk->Mbr );
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+ }
+ PartCount++;
+ Gbr = (GUID_BOOT_RECORD*)&MemBlk->Mbr.BootCode[0];
+ Volume->PartitionOffset = Mul64( Gbr->GuidPart[i].FirstLba, Volume->BlockSize );
+ //
+ // The partition count is incremented by 4 for each new Guid Boot Record,
+ // even if it does not contain 4 partition records. So we may find an empty
+ // partition. Exit with EFI_NOT_FOUND if there is one.
+ //
+ if ( Volume->PartitionOffset == 0 ) {
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessFatDevice
+//
+// Description:
+// Reads recovery capsule from FAT device. First treat device as
+// non-partitioned device. If failed tries to discover primary partitions and
+// search for capsule there.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessFatDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+
+ //
+ // Assume the volume is floppy-formatted
+ //
+ Status = ProcessFatVolume( PeiServices, Volume, FileSize, Buffer );
+
+ if ( !EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ // Not floppy formatted, look for partitions. Rread sector 0 (MBR).
+ //
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Mbr );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if ( MemBlk->Mbr.Sig != 0xaa55 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ PartCount = 0;
+ PartSector = 0;
+ IsMbr = TRUE;
+
+ //
+ // Locate all partitions. Check each one for the recovery file.
+ // The recovery file will be loaded if it is found, and this
+ // function will return EFI_SUCCESS.
+ //
+ do {
+ Status = FindNextPartition( PeiServices, Volume );
+ if ( !EFI_ERROR(Status) ) {
+ Status2 = ProcessFatVolume( PeiServices, Volume, FileSize, Buffer );
+ if ( !EFI_ERROR(Status2) ) {
+ return Status2;
+ }
+ }
+ } while (Status == EFI_SUCCESS);
+
+ return EFI_NOT_FOUND;
+}
+
+#if NTFS_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessNTFSDevice
+//
+// Description:
+// Reads recovery capsule from NTFS device. Tries to discover primary partitions
+// and search for capsule there.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessNTFSDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+
+ //
+ // Assume the volume is floppy-formatted.
+ //
+ Status = ProcessNTFSVolume( PeiServices, Volume, FileSize, Buffer );
+
+ if ( !EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ // Not floppy formatted, look for partitions. Read sector 0 (MBR).
+ //
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Mbr );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if ( MemBlk->Mbr.Sig != 0xaa55 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ PartCount = 0;
+ PartSector = 0;
+ IsMbr = TRUE;
+
+ //
+ // Locate all partitions. Check each one for the recovery file.
+ // The recovery file will be loaded if it is found, and this
+ // function will return EFI_SUCCESS.
+ //
+ do {
+ Status = FindNextPartition( PeiServices, Volume );
+ if ( !EFI_ERROR(Status) ) {
+ Status2 = ProcessNTFSVolume( PeiServices, Volume, FileSize, Buffer );
+ if ( !EFI_ERROR(Status2) ) {
+ return Status2;
+ }
+ }
+ } while (Status == EFI_SUCCESS);
+
+ return EFI_NOT_FOUND;
+}
+#endif
+
+#if EXT_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessExtDevice
+//
+// Description:
+// Reads recovery capsule from Ext(n) device. Tries to discover primary partitions
+// and search for capsule there.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessExtDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+
+ //
+ // Assume the volume is floppy-formatted.
+ //
+ Status = ProcessExtVolume( PeiServices, Volume, FileSize, Buffer );
+
+ if ( !EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ // Not floppy formatted, look for partitions. Read sector 0 (MBR).
+ //
+ Status = ReadDevice( PeiServices, Volume, 0, 512, &MemBlk->Mbr );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if ( MemBlk->Mbr.Sig != 0xaa55 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ PartCount = 0;
+ PartSector = 0;
+ IsMbr = TRUE;
+
+ //
+ // Locate all partitions. Check each one for the recovery file.
+ // The recovery file will be loaded if it is found, and this
+ // function will return EFI_SUCCESS.
+ //
+ do {
+ Status = FindNextPartition( PeiServices, Volume );
+ if ( !EFI_ERROR(Status) ) {
+ Status2 = ProcessExtVolume( PeiServices, Volume, FileSize, Buffer );
+ if ( !EFI_ERROR(Status2) ) {
+ return Status2;
+ }
+ }
+ } while (Status == EFI_SUCCESS);
+
+ return EFI_NOT_FOUND;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessPrimaryVolume
+//
+// Description:
+// Reads recovery capsule from ISO9660 device
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessPrimaryVolume(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ PRIMARY_VOLUME_DESCRIPTOR PriVol;
+ UINT32 RootSize;
+ UINTN RootPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+ UINTN NumberOfFiles;
+ UINT32 i;
+
+ Volume->PartitionOffset = 0;
+ Status = ReadDevice( PeiServices, Volume, 16 * Volume->BlockSize, Volume->BlockSize, &PriVol );
+
+ //
+ //check that we read CD
+ //
+ if ( PriVol.Type != 1 || MemCmp( PriVol.StandardId, "CD001", 5 )) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ //read root directory
+ //
+ RootSize = PriVol.RootDir.DataLength;
+ RootPages = EFI_SIZE_TO_PAGES( RootSize );
+
+ if ( RootBufferSize < EFI_PAGES_TO_SIZE( RootPages )) {
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, RootPages, &Allocate );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ RootBuffer = (UINT8*)((UINTN)Allocate);
+ RootBufferSize = EFI_PAGES_TO_SIZE( RootPages );
+ }
+ MemSet( RootBuffer, RootBufferSize, 0 );
+
+ Status = ReadDevice( PeiServices, Volume, PriVol.RootDir.ExtentOffset * Volume->BlockSize, RootSize, RootBuffer );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ GetFileListFromPrimaryVolume((DIR_RECORD*)RootBuffer, RootSize, &NumberOfFiles, CdRecoveryFiles);
+
+ if(NumberOfFiles == 0)
+ return EFI_NOT_FOUND;
+
+ for(i = 0; i < NumberOfFiles; i++) {
+ if ( *FileSize < CdRecoveryFiles[i]->DataLength )
+ continue;
+
+ Status = ReadDevice( PeiServices, Volume, CdRecoveryFiles[i]->ExtentOffset * Volume->BlockSize, CdRecoveryFiles[i]->DataLength, Buffer );
+ if(EFI_ERROR(Status))
+ continue;
+
+ if(IsValidFile(Buffer, CdRecoveryFiles[i]->DataLength)) {
+ *FileSize = CdRecoveryFiles[i]->DataLength;
+ return EFI_SUCCESS;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ProcessCd
+//
+// Description:
+// Reads recovery capsule ATAPI device. First search for recovery capsule in
+// primary volume. If not found tries to process Eltorito images
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN OUT RC_VOL_INFO *Volume - pointer to volume description structure
+// CHAR8 *FileName - recovery capsule file name
+// UINTN *FileSize - pointer to size of provided buffer
+// OUT VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ProcessCd(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT RC_VOL_INFO *Volume,
+ IN OUT UINTN *FileSize,
+ OUT VOID *Buffer )
+{
+ EFI_STATUS Status;
+ UINT8 Data[2048]; //space for 1 block
+ BOOT_RECORD_VOLUME_DESCRIPTOR *BootDesc;
+ INITIAL_DEFAULT_ENTRY *Entry;
+
+ Status = ProcessPrimaryVolume( PeiServices, Volume, FileSize, Buffer );
+
+ if ( !EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ //file not found in primary volume, check Eltorito partitions
+ //
+ Status = ReadDevice( PeiServices, Volume, 17 * Volume->BlockSize, Volume->BlockSize, Data );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ //
+ //check if it is Eltorito
+ //
+ BootDesc = (BOOT_RECORD_VOLUME_DESCRIPTOR*)Data;
+
+ if ( BootDesc->BootRecordIndicator != 0
+ || MemCmp( &(BootDesc->ISO9660Identifier), "CD001", 5 )
+ || BootDesc->DescriptorVersion != 1
+ || MemCmp( &(BootDesc->BootSystemIdentifier), "EL TORITO SPECIFICATION", 23 )) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ //it is Eltorito, read boot catalog
+ //
+ Status = ReadDevice( PeiServices, Volume, BootDesc->BootCatalogFirstSector * Volume->BlockSize, Volume->BlockSize, Data );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ Entry = (INITIAL_DEFAULT_ENTRY*) &Data[32];
+ Volume->PartitionOffset = Entry->LoadRBA * Volume->BlockSize;
+ Status = ProcessFatDevice( PeiServices, Volume, FileSize, Buffer );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FsRecoveryRead
+//
+// Description:
+// Search for recovery capsule file on all file system devices
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN CHAR8 *FileName - recovery capsule file name
+// IN UINTN DeviceIndex - device index for given BlockIo PPI
+// IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *pBlockIo - pointer to BlockIo PPI
+// UINTN *FileSize - pointer to size of provided buffer
+// VOID *Buffer - pointer to buffer to store data
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FsRecoveryRead(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *pBlockIo,
+ IN OUT UINTN *pSize,
+ OUT VOID *pBuffer )
+{
+ EFI_STATUS Status;
+ RC_VOL_INFO Volume;
+ EFI_PEI_BLOCK_IO_MEDIA Media;
+ UINTN BlockPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+
+ if ( !pBlockIo || !pSize || *pSize && !pBuffer ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MemSet( &Volume, sizeof(RC_VOL_INFO), 0 );
+
+ Status = pBlockIo->GetBlockDeviceMediaInfo( PeiServices, pBlockIo, DeviceIndex, &Media );
+
+ if ( EFI_ERROR( Status )) {
+ return Status;
+ }
+
+ if ( !Media.MediaPresent ) {
+ return EFI_NOT_FOUND;
+ }
+
+ Volume.BlkIo = pBlockIo;
+ Volume.Device = DeviceIndex;
+ Volume.BlockSize = Media.BlockSize;
+
+ //
+ // Allocate memory for MBR, Boot Sector, etc.
+ //
+ BlockPages = EFI_SIZE_TO_PAGES( sizeof(MEMORY_BLOCK) );
+ Status = (*PeiServices)->AllocatePages( PeiServices, EfiBootServicesData, BlockPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ return EFI_NOT_FOUND;
+ }
+ MemBlk = (MEMORY_BLOCK*)((UINTN)Allocate);
+
+ if ( Media.BlockSize == 2048 && CdRecoverySupport ) {
+ Volume.PartitionOffset = 0;
+ Status = ProcessCd( PeiServices, &Volume, pSize, pBuffer );
+ if ( Status == EFI_SUCCESS ) return Status;
+ }
+ if ( FatRecoverySupport ) {
+ Volume.PartitionOffset = 0;
+ Status = ProcessFatDevice( PeiServices, &Volume, pSize, pBuffer );
+ if ( Status == EFI_SUCCESS ) return Status;
+#if NTFS_RECOVERY_SUPPORT
+ }
+ if ( NtfsRecoverySupport ) {
+ Volume.PartitionOffset = 0;
+ Status = ProcessNTFSDevice( PeiServices, &Volume, pSize, pBuffer );
+ if ( Status == EFI_SUCCESS ) return Status;
+#endif
+#if EXT_RECOVERY_SUPPORT
+ }
+ if ( ExtRecoverySupport ) {
+ Volume.PartitionOffset = 0;
+ Status = ProcessExtDevice( PeiServices, &Volume, pSize, pBuffer );
+ if ( Status == EFI_SUCCESS ) return Status;
+#endif
+
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ return Status;
+}
+
+
+/************************************************************************/
+/* Device Recovery Module PPI */
+/************************************************************************/
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetNumberRecoveryCapsules
+//
+// Description:
+// GetNumberRecoveryCapsules function of ppi
+// EFI_PEI_DEVICE_RECOVERY_MODULE_PPI.
+//
+// Input:
+//
+// Output:
+// EFI_SUCCESS - number of recovery capsules returned
+// EFI_INVALID_PARAMETER - the pointer NumberRecoveryCapsules is NULL
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS GetNumberRecoveryCapsules(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ OUT UINTN *NumberRecoveryCapsules )
+{
+ if ( !NumberRecoveryCapsules ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ *NumberRecoveryCapsules = 1;
+ return EFI_SUCCESS;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetRecoveryCapsuleInfo
+//
+// Description:
+// GetRecoveryCapsuleInfo function of ppi EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+// for any block devices including floppies, USB keys, CD-ROMs and HDDs.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PeiServices Structure
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This - pointer to the PPI structure
+// IN UINTN CapsuleInstance - value indicating the instance of the PPI
+// OUT UINTN *Size - Size of the recovery capsule
+// OUT EFI_GUID *CapsuleType OPTIONAL - Type of recovery capsule
+//
+// Output:
+// EFI_SUCCESS - Parameters are valid and output parameters are updated
+// EFI_INVALID_PARAMETER - Size pointer is NULL
+// EFI_NOT_FOUND - asking for a 1 or greater instance of the PPI
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetRecoveryCapsuleInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT UINTN *Size,
+ OUT EFI_GUID *CapsuleType )
+{
+ EFI_STATUS Status;
+
+ if ( !Size ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( CapsuleInstance > 0 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetRecoveryFileInfo(PeiServices, NULL, Size, NULL);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ if ( CapsuleType ) {
+ *CapsuleType = guidBlockDeviceCapsule;
+ }
+ return EFI_SUCCESS;
+}
+
+#define NUMBER_OF_RETRIES 3
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: LoadRecoveryCapsule
+//
+// Description:
+// Locates all EFI_PEI_RECOVERY_BLOCK_IO_PPI PPIs. Calls function
+// GetNumberOfBlockDevices. For each block device, calls the function
+// FsRecoveryRead, to find the recovery image named in var sAmiRomFile.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PeiServices Structure
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This - pointer to the PPI structure
+// IN UINTN CapsuleInstance - value indicating the instance of the PPI
+// OUT VOID *Buffer - contains information read from the block device
+//
+// Output:
+// EFI_SUCCESS - File read from recovery media
+// EFI_INVALID_PARAMETER - Buffer is a NULL pointer
+// EFI_NOT_FOUND - asking for a 1 or greater instance of the PPI
+// Other - return error values from LocatePpi or FsRecoveryRead
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT VOID *Buffer )
+{
+ static EFI_GUID guidBlockIo = EFI_PEI_VIRTUAL_BLOCK_IO_PPI;
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *pDummy;
+ UINTN i;
+ UINTN RecoveryCapsuleSize;
+ BOOLEAN ExtendedVerification;
+
+ PEI_TRACE((-1, PeiServices, "..BLOCK DEVICE.."));
+
+ if ( !Buffer ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( CapsuleInstance > 0 ) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetRecoveryFileInfo(PeiServices, NULL, &RecoveryCapsuleSize, &ExtendedVerification);
+ if ( EFI_ERROR( Status ))
+ return Status;
+
+ i = 0;
+
+ do
+ {
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI *pBlockIo;
+ UINTN NumberBlockDevices;
+ UINTN j;
+ UINTN Size;
+ Status = (*PeiServices)->LocatePpi( PeiServices, &guidBlockIo, i++, &pDummy, &pBlockIo );
+
+ if ( EFI_ERROR( Status )) {
+ break;
+ }
+
+ if (EFI_ERROR( Status = pBlockIo->GetNumberOfBlockDevices(
+ PeiServices, pBlockIo, &NumberBlockDevices))) {
+ continue;
+ }
+
+ for ( j = 0; j < NumberBlockDevices; j++ ) {
+ UINTN k;
+ Size = RecoveryCapsuleSize;
+
+ for ( k = 0; k < NUMBER_OF_RETRIES; k++ )
+ {
+ Status = FsRecoveryRead(
+ PeiServices, j, pBlockIo,
+ &Size, Buffer
+ );
+
+ if ( !EFI_ERROR(Status) ){
+ if(ExtendedVerification || Size == RecoveryCapsuleSize )
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while ( TRUE );
+ return Status;
+}
+
+/************************************************************************/
+/* Entry Point */
+/************************************************************************/
+EFI_PEI_DEVICE_RECOVERY_MODULE_PPI BlockDeviceRecoveryModule = {
+ GetNumberRecoveryCapsules, GetRecoveryCapsuleInfo, LoadRecoveryCapsule
+};
+
+// PPI to be installed
+static EFI_PEI_PPI_DESCRIPTOR BlockDeviceRecoveryPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidRecoveryDevice, &BlockDeviceRecoveryModule
+ }
+};
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: BlockDeviceRecoveryEntry
+//
+// Description:
+// Installs EFI_PEI_DEVICE_RECOVERY_MODULE_PPI for loading recovery
+// images from block devices such as floppies, USB keys, HDDs or CD-ROMs
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS BlockDeviceRecoveryEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ ThisPeiServices = PeiServices;
+ return (*PeiServices)->InstallPpi( PeiServices, BlockDeviceRecoveryPpiList );
+}
+
+//************************** AMI custom eLink implementation *******************
+
+VOID AmiGetFileListFromPrimaryVolume(
+ IN DIR_RECORD *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_RECORD **Buffer
+)
+{
+ UINT32 Count = 0;
+ CHAR8 *DirFileName;
+ UINT32 FileNameSize;
+
+ VOID *FileName;
+ UINTN FileSize;
+ EFI_STATUS Status;
+
+
+ *NumberOfFiles = 0; //no files found yet
+
+ Status = GetRecoveryFileInfo(ThisPeiServices, &FileName, &FileSize, NULL);
+ if(EFI_ERROR(Status))
+ return;
+
+ //
+ //find file in root directory
+ //
+ while ( Count < RootSize ) {
+ DirFileName = (CHAR8*)(Root + 1);
+
+ if(Root->Length == 0)
+ return;
+
+ // Find the length of the file name. The ISO9660 spec has the following structure
+ // up to 8 characters then a '.' then up to 3 more characters then a ';'
+ // then the digits that make up a number between 0 and 32767
+ // The filename search uses all characters up to the ';'
+ FileNameSize = 0;
+ while(DirFileName[FileNameSize] != ';' && (FileNameSize < Root->LengthOfFileId))
+ FileNameSize++;
+
+ if (!EFI_ERROR(FileSearch((CHAR8*)FileName, DirFileName, FALSE, FileNameSize))) {
+ Buffer[*NumberOfFiles] = Root;
+ (*NumberOfFiles)++;
+ break;
+ }
+
+ Count += Root->Length;
+ (UINT8 *)Root += Root->Length;
+ }
+}
+
+#if SEARCH_FAT_PATH
+BOOLEAN IsolateName (
+ IN CHAR8 **FilePath,
+ OUT CHAR8 **NextName
+)
+{
+ UINTN len;
+ BOOLEAN GotName;
+ UINTN i;
+ CHAR8 *TempPath;
+
+ TempPath = *FilePath;
+ len = Strlen(TempPath);
+ GotName = TRUE;
+ for ( i = 0; i < len; i++ ) {
+ if ( TempPath[i] == 0x5C ) { // "\"
+ GotName = FALSE;
+ TempPath[i] = 0;
+ *NextName = TempPath + i + 1;
+ return GotName;
+ }
+ }
+ return GotName;
+}
+
+#endif
+
+VOID AmiGetFileListFromFatVolume(
+ IN DIR_ENTRY *Root,
+ IN UINT32 RootEntries,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY **Buffer
+)
+{
+ UINT32 i;
+
+ VOID *FileName;
+ UINTN FileSize;
+ EFI_STATUS Status;
+ UINT32 DirEntries;
+ DIR_ENTRY *DirPtr;
+ CHAR8 *FilePath;
+#if SEARCH_FAT_PATH
+ UINT32 DirSize;
+ CHAR8 *NextName;
+ UINTN DirPages;
+ EFI_PHYSICAL_ADDRESS Allocate;
+ UINT32 Cluster;
+#endif
+
+ *NumberOfFiles = 0; //no files found yet
+
+ Status = GetRecoveryFileInfo(ThisPeiServices, &FileName, &FileSize, NULL);
+ if(EFI_ERROR(Status))
+ return;
+
+ FilePath = FileName;
+ DirEntries = RootEntries;
+ DirPtr = Root;
+#if SEARCH_FAT_PATH
+ FilePath = (CHAR8*)FileName;
+ NextName = FilePath;
+
+ while ( IsolateName (&FilePath, &NextName) == FALSE ) {
+ //
+ //Find path name in directory
+ //
+ for(i = 0; i < DirEntries; i++) {
+ if((DirPtr[i].FileName[0] == 0xE5) || (DirPtr[i].FileName[0] == 0))
+ continue;
+
+ if(!EFI_ERROR(FileSearch((CHAR8*)FilePath, DirPtr[i].FileName, TRUE, FAT_FILE_NAME_SIZE))) {
+ //
+ // A match was found...
+ // Update FilePath to next name.
+ // Update DirPtr to this directory, and read it in
+ //
+ // *REMOVED* DirSize = DirPtr[i].FileSize;
+ //
+ // The size of a directory is not stored in it's directory entry,
+ // So we will only read in one cluster for now.
+ //
+ DirSize = ThisVolume->BytesPerCluster;
+ DirEntries = DirSize / 32;
+ Cluster = DirPtr[i].FirstClusterLo + (DirPtr[i].FirstClusterHi << 16);
+
+ DirPages = EFI_SIZE_TO_PAGES( DirSize );
+
+ if ( DirSize < EFI_PAGES_TO_SIZE( DirPages )) {
+ Status = (*ThisPeiServices)->AllocatePages( ThisPeiServices,
+ EfiBootServicesData, DirPages, &Allocate );
+ if ( EFI_ERROR( Status )) {
+ *NumberOfFiles = 0;
+ return;
+ }
+
+ DirPtr = (DIR_ENTRY*)((UINTN)Allocate);
+ DirSize = EFI_PAGES_TO_SIZE( DirPages );
+ }
+ MemSet( DirPtr, DirSize, 0 );
+
+ Status = GetFatData( ThisPeiServices, ThisVolume, Cluster, DirSize, DirPtr );
+ if ( EFI_ERROR( Status )) {
+ *NumberOfFiles = 0;
+ return;
+ }
+ FilePath = NextName;
+ break;
+ }
+ }
+ }
+#endif
+ //
+ // Find file in directory
+ //
+ for(i = 0; i < DirEntries; i++) {
+ if((DirPtr[i].FileName[0] == 0xE5) || (DirPtr[i].FileName[0] == 0))
+ continue;
+
+ if(!EFI_ERROR(FileSearch((CHAR8*)FilePath, DirPtr[i].FileName, TRUE, FAT_FILE_NAME_SIZE))) {
+ Buffer[*NumberOfFiles] = &DirPtr[i];
+ *NumberOfFiles = 1;
+ break;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AmiGetFileListFromNtfsVolume
+//
+// Description:
+// Gets a list of valid recovery files from an NTFS volume.
+// As currently written, gets only one file.
+//
+// Input:
+// UINT8 *Root - Pointer to a buffer containing the root directory
+// UINT32 RootSize - Size of the root directory
+// UINTN *NumberOfFiles - Pointer to number of files found
+// INDEX_ENTRY **Buffer - Pointer to buffer containing index entry of
+// the file that was found.
+//
+// Output:
+// None - returned in variables.
+//
+// Notes:
+// This is an e-linked function, which can be replaced.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AmiGetFileListFromNtfsVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT INDEX_ENTRY **Buffer
+)
+{
+#if NTFS_RECOVERY_SUPPORT
+ UINT8 i;
+ UINT32 IndexSize;
+ UINT32 IndexSize2;
+ UINTN Offset;
+ UINT8 *TmpPtr;
+ CHAR16 *NamePtr;
+ CHAR8 TmpFileName[13];
+ UINT8 LfnSize;
+ UINT16 EntrySize;
+ INDEX_ENTRY *IndxPtr;
+ VOID *FileName;
+ UINTN FileSize;
+ EFI_STATUS Status;
+
+ *NumberOfFiles = 0; //no files found yet
+
+ Status = GetRecoveryFileInfo(ThisPeiServices, &FileName, &FileSize, NULL);
+ if(EFI_ERROR(Status))
+ return;
+
+ if (ResidentPresent) { // If resident index found...
+ TmpPtr = &MemBlk->ResidentIndex[0];
+ IndexSize = ResidentSize;
+
+ do { // loop inside the index
+ EntrySize = ((INDEX_ENTRY*)TmpPtr)->INDE_EntrySize;
+ LfnSize = ((INDEX_ENTRY*)TmpPtr)->INDE_NameLength;
+ if (LfnSize > 12) LfnSize = 12; // Limit name to 12 chars
+ NamePtr = &((INDEX_ENTRY*)TmpPtr)->INDE_Name[0];
+ for ( i=0; i<LfnSize; i++ )
+ {
+ TmpFileName[i] = (CHAR8)(CHAR16)NamePtr[i];
+ }
+ TmpFileName[i] = 0; // Zero-terminate name
+
+ if(!EFI_ERROR(FileSearch((CHAR8*)FileName, TmpFileName, FALSE, LfnSize))) {
+ IndxPtr = (INDEX_ENTRY*)&TmpPtr[0];
+ Buffer[*NumberOfFiles] = IndxPtr; // Save pointer to this entry
+ *NumberOfFiles = 1;
+ return;
+ }
+
+ TmpPtr += EntrySize;
+ IndexSize -= EntrySize;
+ if ( IndexSize < MINIMUM_ENTRY_SIZE ) break;
+
+ } while (IndexSize);
+ }
+
+ do { // do loop handling indexes in the root
+ Offset = 0;
+ // Look for "INDX", start of index record
+ if ( (Root[0] == 0x49) && \
+ (Root[1] == 0x4E) && \
+ (Root[2] == 0x44) && \
+ (Root[3] == 0x58) )
+ {
+ IndexSize = ((INDEX_RECORD*)Root)->INDR_IndxEntrySize;
+ IndexSize2 = IndexSize;
+ Offset += ((INDEX_RECORD*)Root)->INDR_IndxEntryOff + \
+ EFI_FIELD_OFFSET(INDEX_RECORD, INDR_IndxEntryOff);
+ TmpPtr = Root;
+ TmpPtr += Offset; // Point to first entry in index
+ if (IndexSize < MINIMUM_ENTRY_SIZE) { // Empty index
+ return;
+ }
+ } else return; // no index found
+
+ do { // loop inside the index
+ EntrySize = ((INDEX_ENTRY*)TmpPtr)->INDE_EntrySize;
+ LfnSize = ((INDEX_ENTRY*)TmpPtr)->INDE_NameLength;
+ if (LfnSize > 12) LfnSize = 12; // Limit name to 12 chars
+ NamePtr = &((INDEX_ENTRY*)TmpPtr)->INDE_Name[0];
+ for ( i=0; i<LfnSize; i++ )
+ {
+ TmpFileName[i] = (CHAR8)(CHAR16)NamePtr[i];
+ }
+ TmpFileName[i] = 0; // Zero-terminate name
+
+ if(!EFI_ERROR(FileSearch((CHAR8*)FileName, TmpFileName, FALSE, LfnSize))) {
+ IndxPtr = (INDEX_ENTRY*)&TmpPtr[0];
+ Buffer[*NumberOfFiles] = IndxPtr; // Save pointer to this entry
+ *NumberOfFiles = 1;
+ return;
+ }
+
+ TmpPtr += EntrySize;
+ IndexSize -= EntrySize;
+ if ( IndexSize < MINIMUM_ENTRY_SIZE ) break;
+
+ } while (IndexSize);
+ if ( IndexSize2 < 0x1000 ) {
+ IndexSize2 = 0x1000;
+ } else {
+ IndexSize2 = (IndexSize2 + 0x100) & 0xffffff00 ; // Round off
+ }
+ Root += IndexSize2;
+ RootSize -= IndexSize2;
+
+ } while (RootSize);
+#else
+ *NumberOfFiles = 0; //no files found
+ return;
+#endif
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AmiGetFileListFromExtVolume
+//
+// Description:
+// Gets a list of valid recovery files from an EXT(n) volume.
+// As currently written, gets only one file.
+//
+// Input:
+// UINT8 *Root - Pointer to a buffer containing the root directory
+// UINT32 RootSize - Size of the root directory
+// UINTN *NumberOfFiles - Pointer to number of files found
+// DIR_ENTRY_EXT **Buffer - Pointer to buffer containing index entry of
+// the file that was found.
+//
+// Output:
+// None - returned in variables.
+//
+// Notes:
+// This is an e-linked function, which can be replaced.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID AmiGetFileListFromExtVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY_EXT **Buffer
+)
+{
+#if EXT_RECOVERY_SUPPORT
+ EFI_STATUS Status;
+ DIR_ENTRY_EXT *TmpPtr;
+ UINT16 EntryLength;
+ UINT8 NameLength;
+ VOID *FileName;
+ UINTN FileSize;
+ UINT8 i;
+ CHAR8 TmpFileName[13];
+
+ *NumberOfFiles = 0; //no files found yet
+
+ Status = GetRecoveryFileInfo(ThisPeiServices, &FileName, &FileSize, NULL);
+ if(EFI_ERROR(Status))
+ return;
+
+ do { // do loop handling entries in the root
+
+ TmpPtr = (DIR_ENTRY_EXT*)&Root[0];
+ EntryLength = TmpPtr->DIR_EntryLength;
+ if (EntryLength == 0) break; // End of directory, file not found
+ NameLength = TmpPtr->DIR_NameLength;
+ if (NameLength > 12) NameLength = 12;
+ for ( i=0; i<NameLength; i++ )
+ {
+ TmpFileName[i] = TmpPtr->DIR_Name[i];
+ }
+ TmpFileName[i] = 0; // Zero-terminate name
+
+ if(!EFI_ERROR(FileSearch((CHAR8*)FileName,
+ TmpFileName,
+ FALSE,
+ NameLength))) {
+ Buffer[*NumberOfFiles] = TmpPtr; // Save pointer to this entry
+ *NumberOfFiles = 1;
+ return;
+ }
+
+ Root += EntryLength;
+ RootSize -= EntryLength;
+
+ } while (RootSize);
+#else
+ *NumberOfFiles = 0; //no files found
+ return;
+#endif
+}
+
+BOOLEAN AmiIsValidFile(
+ IN VOID *FileData,
+ IN UINTN FileSize
+)
+{
+ return TRUE;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/IdeRecovery.c b/Core/EM/Recovery/IdeRecovery.c
new file mode 100644
index 0000000..8ece24c
--- /dev/null
+++ b/Core/EM/Recovery/IdeRecovery.c
@@ -0,0 +1,2172 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/Recovery/IdeRecovery.c 15 4/02/12 12:54a Srilathasc $
+//
+// $Revision: 15 $
+//
+// $Date: 4/02/12 12:54a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/Recovery/IdeRecovery.c $
+//
+// 15 4/02/12 12:54a Srilathasc
+// [TAG] EIP81405
+// [Category] Bug Fix
+// [Symptom] Recovery mode did not work in hard disk
+// [RootCause] Sufficient timeout to wait for DRQ was not given after
+// command was written in AtaPioDataIn()
+// [Solution] Increase the TIMEOUT to 10 seconds after the command is
+// complete
+//
+// [Files] IdeRecovery.c
+//
+// 14 2/21/12 5:04a Rameshr
+// [TAG] EIP75596
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Boot to recovery mode without media in the CD drive.First
+// time it will fail and next time while inserting Media , still recovery
+// not success from CD.
+// [RootCause] Atapi_DetectMedia will get called and irrespective of
+// device status LookedForMedia flag getting updated
+// [Solution] LookedForMedia flag updated only when the success
+// detection of Media in the ODD
+// [Files] IdeRecovery.c
+//
+// 13 7/07/11 3:20a Lavanyap
+// [TAG] EIP59029
+// [Category] Bug Fix
+// [Symptom] Recovery failed in IDE mode in VIA platform.
+// [RootCause] BSY/DRQ status checking was not done on the right port.
+// [Solution] Select the proper device before checking the device
+// status.
+// [Files] IdeRecovery.c
+//
+// 12 5/04/11 12:20p Artems
+// Bug fix: rollback previous check-in changes
+//
+// 11 2/14/11 4:06p Yul
+// [TAG] EIP38288
+// [Category] Enhanced
+// [Description] Klocwork Issues II - Recovery
+//
+// 10 1/07/10 12:01p Robert
+// In Ata_ReadSectors() Change the SectorCount variable to UINT16,
+// removed the typecasting when setting this variable and added a
+// typecasting to UINT8 when call the AtaPioDataIn()
+// Removed previous changes for clearer functionality
+//
+// 9 1/05/10 12:13p Robert
+// in Ata_ReadSectors() if the need arises to call AtaPioDataIn with
+// SectorCount == MaxBlock, no data was ever read. A special case had to
+// be created to handle the case when SectorCount == MaxBlock.
+// Refer to EIP #33174 for more details
+//
+// 8 7/01/09 4:19p Rameshr
+// Coding Standard and File header updated.
+//
+// 7 3/04/09 1:32p Felixp
+// Address in the file header is updated.
+//
+// 6 2/26/09 5:38p Felixp
+// File header is updated (no code changes).
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: IdeRecovery.c
+//
+// Description: IDE Recovery Implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: IdeRecovery.c - PEI driver
+//
+// Description: Implements EFI_PEI_RECOVERY_BLOCK_IO_PPI for ATA and ATAPI devices.
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include <PEI.h>
+#include <AmiPeiLib.h>
+#include <AmiLib.h>
+#include <Ppi\DeviceRecoveryBlockIo.h>
+#include <Ppi\Stall.h>
+#include <Protocol\BlockIo.h>
+#include <Ppi\AtaController.h>
+
+
+EFI_GUID gPeiStallPpiGuid = EFI_PEI_STALL_PPI_GUID;
+EFI_GUID gPeiAtaControllerPpiGuid = PEI_ATA_CONTROLLER_PPI_GUID;
+EFI_GUID gPeiBlockIoPpiGuid = EFI_PEI_VIRTUAL_BLOCK_IO_PPI;
+EFI_GUID gIdeRecoveryNativeModePpiGuid = PEI_IDE_RECOVERY_NATIVE_MODE_PPI_GUID;
+
+//----------------------------------------------------------------------
+
+//Atapi command definitions
+
+#define EFI_MIN( a, b ) (((a) < (b)) ? (a) : (b))
+
+#define ATAPI_SIGNATURE 0xEB14
+
+#define CD_ROM_DEVICE 0x5
+
+#define SK_NO_SENSE 0
+#define SK_NOT_READY 2
+#define SK_UNIT_ATTENTION 6
+
+#define MAX_SENSE_KEY_COUNT 6
+
+#pragma pack(1)
+
+typedef struct
+{
+ UINT16 GeneralConfiguration_0;
+ UINT16 Data_1_58[58];
+ UINT32 TotalUserAddressableSectors_60;
+ UINT16 Data_61_255[195];
+} ATA_IDENTIFY_DATA;
+
+typedef struct
+{
+ UINT8 PeripheralDeviceType_0 : 5;
+ UINT8 Reserved_0 : 3;
+ UINT8 Data_1_95[95];
+} INQUIRY_DATA;
+
+typedef struct
+{
+ UINT8 Data_0_1[2];
+ UINT8 SenseKey_2 : 4;
+ UINT8 Data_2 : 4;
+ UINT8 Data_3_6[4];
+ UINT8 AdditionalSenseLength_7;
+ UINT8 Data_8_11[4];
+ UINT8 AdditionalSenseCode_12;
+ UINT8 AdditionalSenseCodeQualifier_13;
+ UINT8 Data_14_17[4];
+} REQUEST_SENSE_DATA;
+
+typedef struct
+{
+ UINT8 LastLba0;
+ UINT8 LastLba1;
+ UINT8 LastLba2;
+ UINT8 LastLba3;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+#pragma pack()
+
+#define PACKET_CMD 0xA0
+#define ATA_IDENTIFY_DEVICE_CMD 0xEC
+#define ATA_READ_SECTOR_CMD 0x20
+
+#pragma pack(1)
+
+typedef struct
+{
+ UINT8 OperationCode_0;
+ UINT8 Data_1_3[3];
+ UINT8 AllocationLength_4;
+ UINT8 Data_5_11[7];
+} GENERIC_CMD;
+
+typedef struct
+{
+ UINT8 OperationCode_0;
+ UINT8 Data_1;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 Data_6;
+ UINT8 TransferLengthMSB;
+ UINT8 TransferLengthLSB;
+ UINT8 Data_9_11[3];
+} READ10_CMD;
+
+typedef union
+{
+ UINT16 Data16[6];
+ GENERIC_CMD Cmd;
+ READ10_CMD Read10;
+} ATAPI_PACKET_COMMAND;
+
+#pragma pack()
+
+#define TEST_UNIT_READY 0x00
+#define REQUEST_SENSE 0x03
+#define INQUIRY 0x12
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+
+#define DEFAULT_CTL (0x0a) // default content of device control register, disable INT
+#define DEFAULT_CMD (0xa0)
+
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+#pragma pack(1)
+
+// IDE registers bit definitions
+
+// Err Reg
+#define ABRT_ERR BIT02 // Aborted Command
+
+
+// Device/Head Reg
+#define LBA_MODE BIT06
+
+// Status Reg
+#define BSY BIT07 // Controller Busy
+#define DRDY BIT06 // Drive Ready
+#define DWF BIT05 // Drive Write Fault
+#define DRQ BIT03 // Data Request
+#define CORR BIT02 // Corrected Data
+#define ERR BIT00 // Error
+
+#pragma pack()
+
+#define STALL_1_MILLI_SECOND 1000 // stall 1 ms
+
+#define TIMEOUT 1000 // 1 second
+#define COMMAND_COMPLETE_TIMEOUT 10000 // 10 seconds
+#define LONGTIMEOUT 5000 // 5 seconds
+
+//----------------------------------------------------------------------
+
+typedef enum {
+ EnumerateAtapi, EnumerateAta
+} ENUMERATE_TYPE;
+typedef enum {
+ IdeLegacy, IdeNative, IdeMaxMode
+} EFI_IDE_MODE;
+typedef enum {
+ IdePrimary, IdeSecondary, IdeMaxChannel
+} EFI_IDE_CHANNEL;
+typedef enum {
+ IdeMaster, IdeSlave, IdeMaxDevice
+} EFI_IDE_DEVICE;
+
+// IDE Registers
+typedef union
+{
+ UINT16 Command; // when write
+ UINT16 Status; // when read
+} IDE_CMD_OR_STATUS;
+
+typedef union
+{
+ UINT16 Error; // when read
+ UINT16 Feature; // when write
+} IDE_ERROR_OR_FEATURE;
+
+typedef union
+{
+ UINT16 AltStatus; // when read
+ UINT16 DeviceControl; // when write
+} IDE_AltStatus_OR_DeviceControl;
+
+
+// IDE registers set
+typedef struct
+{
+ UINT16 Data;
+ IDE_ERROR_OR_FEATURE Reg1;
+ UINT16 SectorCount;
+ UINT16 SectorNumber;
+ UINT16 CylinderLsb;
+ UINT16 CylinderMsb;
+ UINT16 Head;
+ IDE_CMD_OR_STATUS Reg;
+
+ IDE_AltStatus_OR_DeviceControl Alt;
+ UINT16 DriveAddress;
+} IDE_BASE_REGISTERS;
+
+typedef struct
+{
+ UINT8 Device;
+ BOOLEAN LookedForMedia;
+ IDE_BASE_REGISTERS *IdeIoPortRegisters;
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+} IDE_RECOVERY_DEVICE_INFO;
+
+#define MAX_DEVICE_COUNT 8
+
+typedef struct
+{
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI RecoveryBlkIo;
+
+ BOOLEAN HaveEnumeratedDevices;
+ UINTN DeviceCount;
+ IDE_RECOVERY_DEVICE_INFO *DeviceInfo[MAX_DEVICE_COUNT];
+} IDE_RECOVERY_BLK_IO_DEV;
+
+// IDE registers' fixed address
+IDE_BASE_REGISTERS PrimaryChannelLegacyIdeIoPortRegisters = {
+ 0x1f0, 0x1f1, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, 0x1f7, 0x3f6, 0x3f7
+};
+
+IDE_BASE_REGISTERS SecondaryChannelLegacyIdeIoPortRegisters = {
+ 0x170, 0x171, 0x172, 0x173, 0x174, 0x175, 0x176, 0x177, 0x376, 0x377
+};
+
+//AtaAtapiCommonInit should only be called once
+BOOLEAN gHaveCalledAtaAtapiCommonInit = FALSE;
+
+BOOLEAN gIdeRecoveryNativeModeSupport = FALSE;
+
+IDE_BASE_REGISTERS PrimaryChannelNativeIdeIoPortRegisters = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 0, 1
+};
+
+IDE_BASE_REGISTERS SecondaryChannelNativeIdeIoPortRegisters = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 0, 1
+};
+
+IDE_BASE_REGISTERS *gNativeModePortRegsiters;
+UINT8 gNativeIdeCount = 0;
+
+
+//----------------------------------------------------------------------
+
+// PEI Recovery Block I/O PPI
+
+EFI_STATUS AtaAtapiCommonInit (
+ IN EFI_PEI_SERVICES **PeiServices );
+
+EFI_STATUS Atapi_GetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices );
+EFI_STATUS Atapi_GetBlockDeviceMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo );
+EFI_STATUS Atapi_ReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+EFI_STATUS Ata_GetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices );
+EFI_STATUS Ata_GetBlockDeviceMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo );
+EFI_STATUS Ata_ReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer );
+
+// Private functions
+VOID EnumerateDevices (
+ IN OUT IDE_RECOVERY_BLK_IO_DEV *IdeRecoveryBlkIoDev,
+ IN ENUMERATE_TYPE EnumerateType );
+BOOLEAN Atapi_DiscoverDevice (
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+BOOLEAN Ata_DiscoverDevice (
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+
+EFI_STATUS AtapiPacketCommandIn (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS Inquiry (
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+EFI_STATUS Atapi_DetectMedia (
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+EFI_STATUS TestUnitReady (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+EFI_STATUS RequestSense (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ OUT REQUEST_SENSE_DATA *SenseBuffers,
+ OUT UINT8 *SenseCounts );
+EFI_STATUS ReadCapacity (
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo );
+EFI_STATUS Atapi_ReadSectors (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ OUT VOID *Buffer,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN UINTN BlockSize );
+
+EFI_STATUS AtaPioDataIn (
+ IN IDE_BASE_REGISTERS *IdeIoPortRegisters,
+ OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb,
+ IN UINT8 Device,
+ IN UINT8 Command );
+EFI_STATUS AtaIdentify (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ OUT ATA_IDENTIFY_DATA *AtaIdentifyData );
+EFI_STATUS Ata_ReadSectors (
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ OUT VOID *Buffer,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN UINTN BlockSize );
+
+EFI_STATUS WaitForBitsToClear (
+ IN UINT16 Register,
+ IN UINT8 Bits,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS WaitForBSYClear (
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS DRQClear (
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS DRQClear2 (
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds );
+
+EFI_STATUS DRQReadyHelper (
+ IN UINT16 StatusRegister,
+ IN UINT16 ErrorRegister,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS DRQReady (
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds );
+EFI_STATUS DRQReady2 (
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds );
+
+EFI_STATUS CheckErrorStatus (
+ IN UINT16 StatusReg );
+
+VOID ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Size );
+
+//----------------------------------------------------------------------
+
+EFI_PEI_PPI_DESCRIPTOR Atapi_PpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiBlockIoPpiGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR Ata_PpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiBlockIoPpiGuid,
+ NULL
+};
+
+static EFI_PEI_SERVICES **gPeiServices = NULL;
+static EFI_PEI_STALL_PPI *gStallPpi = NULL;
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_RecoveryPeimEntry
+//
+// Description: Installs EFI_PEI_RECOVERY_BLOCK_IO_PPI for ATAPI devices.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_RecoveryPeimEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ IDE_RECOVERY_BLK_IO_DEV *Atapi_BlkIoDev = NULL;
+
+ if ( !gPeiServices ) {
+ gPeiServices = PeiServices;
+ }
+
+ Status = (**PeiServices).AllocatePool( PeiServices, sizeof(IDE_RECOVERY_BLK_IO_DEV), &Atapi_BlkIoDev );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Atapi_BlkIoDev->HaveEnumeratedDevices = FALSE;
+ Atapi_BlkIoDev->DeviceCount = 0;
+
+ Atapi_BlkIoDev->RecoveryBlkIo.GetNumberOfBlockDevices = Atapi_GetNumberOfBlockDevices;
+ Atapi_BlkIoDev->RecoveryBlkIo.GetBlockDeviceMediaInfo = Atapi_GetBlockDeviceMediaInfo;
+ Atapi_BlkIoDev->RecoveryBlkIo.ReadBlocks = Atapi_ReadBlocks;
+ Atapi_PpiDescriptor.Ppi = &Atapi_BlkIoDev->RecoveryBlkIo;
+
+ Status = (**PeiServices).InstallPpi( PeiServices, &Atapi_PpiDescriptor );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_RecoveryPeimEntry
+//
+// Description: Installs EFI_PEI_RECOVERY_BLOCK_IO_PPI for ATA devices.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Ata_RecoveryPeimEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ IDE_RECOVERY_BLK_IO_DEV *Ata_BlkIoDev = NULL;
+
+ if ( !gPeiServices ) {
+ gPeiServices = PeiServices;
+ }
+
+ Status = (**PeiServices).AllocatePool( PeiServices, sizeof(IDE_RECOVERY_BLK_IO_DEV), &Ata_BlkIoDev );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ata_BlkIoDev->HaveEnumeratedDevices = FALSE;
+ Ata_BlkIoDev->DeviceCount = 0;
+
+ Ata_BlkIoDev->RecoveryBlkIo.GetNumberOfBlockDevices = Ata_GetNumberOfBlockDevices;
+ Ata_BlkIoDev->RecoveryBlkIo.GetBlockDeviceMediaInfo = Ata_GetBlockDeviceMediaInfo;
+ Ata_BlkIoDev->RecoveryBlkIo.ReadBlocks = Ata_ReadBlocks;
+ Ata_PpiDescriptor.Ppi = &Ata_BlkIoDev->RecoveryBlkIo;
+
+ Status = (**PeiServices).InstallPpi( PeiServices, &Ata_PpiDescriptor );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AtaAtapiCommonInit
+//
+// Description: Called by Atapi_RecoveryPeimEntry and Ata_RecoveryPeimEntry
+// functions. Initializes stuff, including
+// gIdeRecoveryNativeModeSupport,
+// PrimaryChannelNativeIdeIoPortRegisters,
+// SecondaryChannelNativeIdeIoPortRegisters.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaAtapiCommonInit(
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS LegacyStatus = EFI_NOT_FOUND;
+ PEI_ATA_CONTROLLER_PPI *AtaControllerPpi = NULL;
+ PEI_IDE_RECOVERY_NATIVE_MODE_PPI *IdeRecoveryNativeModePpi = NULL;
+ UINT8 i = 0;
+ UINT8 Index = 0;
+
+
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid, 0, NULL, &gStallPpi );
+
+ if ( EFI_ERROR( Status )) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiAtaControllerPpiGuid, 0, NULL, &AtaControllerPpi );
+
+ if ( !(EFI_ERROR( Status ))) {
+ LegacyStatus = AtaControllerPpi->EnableAtaChannel( PeiServices, AtaControllerPpi, PEI_ICH_IDE_PRIMARY | PEI_ICH_IDE_SECONDARY );
+ }
+
+ //
+ //Find Number of Native mode IDE ppi installed
+ //
+ Index = 0;
+
+ do
+ {
+ Status = (**PeiServices).LocatePpi( PeiServices, &gIdeRecoveryNativeModePpiGuid, Index, NULL, &IdeRecoveryNativeModePpi );
+
+ if ( !(EFI_ERROR( Status ))) {
+ Index++;
+ gNativeIdeCount++;
+ }
+ } while ( Status == EFI_SUCCESS );
+
+ //
+ //if Legacy mode init fails and if there is no native PPI return with error.
+ //
+ if ((gNativeIdeCount == 00) && (LegacyStatus != EFI_SUCCESS)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = (**PeiServices).AllocatePool( PeiServices, sizeof(IDE_BASE_REGISTERS) * 2 * gNativeIdeCount, &gNativeModePortRegsiters );
+
+ //
+ //Fill the base address values in gNativeModePortRegsiters
+ //
+ Index = 0;
+
+ do
+ {
+ Status = (**PeiServices).LocatePpi( PeiServices, &gIdeRecoveryNativeModePpiGuid, Index, NULL, &IdeRecoveryNativeModePpi );
+
+ if ( !(EFI_ERROR( Status ))) {
+ gIdeRecoveryNativeModeSupport = TRUE;
+ gNativeModePortRegsiters[i].Data = PrimaryChannelNativeIdeIoPortRegisters.Data + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].Reg1.Error = PrimaryChannelNativeIdeIoPortRegisters.Reg1.Error + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].SectorCount = PrimaryChannelNativeIdeIoPortRegisters.SectorCount + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].SectorNumber = PrimaryChannelNativeIdeIoPortRegisters.SectorNumber + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].CylinderLsb = PrimaryChannelNativeIdeIoPortRegisters.CylinderLsb + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].CylinderMsb = PrimaryChannelNativeIdeIoPortRegisters.CylinderMsb + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].Head = PrimaryChannelNativeIdeIoPortRegisters.Head + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].Reg.Command = PrimaryChannelNativeIdeIoPortRegisters.Reg.Command + IdeRecoveryNativeModePpi->PCMDBarAddress;
+ gNativeModePortRegsiters[i].Alt.AltStatus = PrimaryChannelNativeIdeIoPortRegisters.Alt.AltStatus + IdeRecoveryNativeModePpi->PCNLBarAddress;
+ gNativeModePortRegsiters[i].DriveAddress = PrimaryChannelNativeIdeIoPortRegisters.DriveAddress + IdeRecoveryNativeModePpi->PCNLBarAddress;
+
+ gNativeModePortRegsiters[i + 1].Data = SecondaryChannelNativeIdeIoPortRegisters.Data + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].Reg1.Error = SecondaryChannelNativeIdeIoPortRegisters.Reg1.Error + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].SectorCount = SecondaryChannelNativeIdeIoPortRegisters.SectorCount + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].SectorNumber = SecondaryChannelNativeIdeIoPortRegisters.SectorNumber += IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].CylinderLsb = SecondaryChannelNativeIdeIoPortRegisters.CylinderLsb + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].CylinderMsb = SecondaryChannelNativeIdeIoPortRegisters.CylinderMsb + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].Head = SecondaryChannelNativeIdeIoPortRegisters.Head + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].Reg.Command = SecondaryChannelNativeIdeIoPortRegisters.Reg.Command + IdeRecoveryNativeModePpi->SCMDBarAddress;
+ gNativeModePortRegsiters[i + 1].Alt.AltStatus = SecondaryChannelNativeIdeIoPortRegisters.Alt.AltStatus + IdeRecoveryNativeModePpi->SCNLBarAddress;
+ gNativeModePortRegsiters[i + 1].DriveAddress = SecondaryChannelNativeIdeIoPortRegisters.DriveAddress + IdeRecoveryNativeModePpi->SCNLBarAddress;
+ i = i + 2;
+ Index++;
+ }
+ } while ( Status == EFI_SUCCESS );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_GetNumberOfBlockDevices
+//
+// Description: GetNumberOfBlockDevices function of
+// EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_GetNumberOfBlockDevices(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices )
+{
+ IDE_RECOVERY_BLK_IO_DEV *Atapi_BlkIoDev = NULL;
+
+ if ( This == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Atapi_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( !Atapi_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Atapi_BlkIoDev, EnumerateAtapi );
+ Atapi_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+ *NumberBlockDevices = Atapi_BlkIoDev->DeviceCount;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_GetBlockDeviceMediaInfo
+//
+// Description: GetBlockDeviceMediaInfo function of
+// EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_GetBlockDeviceMediaInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo )
+{
+ IDE_RECOVERY_BLK_IO_DEV *Atapi_BlkIoDev = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (MediaInfo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Atapi_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( !Atapi_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Atapi_BlkIoDev, EnumerateAtapi );
+ Atapi_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+
+ if ( DeviceIndex > (Atapi_BlkIoDev->DeviceCount - 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( !Atapi_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia ) {
+ Status = Atapi_DetectMedia( Atapi_BlkIoDev->DeviceInfo[DeviceIndex] );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+ Atapi_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia = TRUE;
+ }
+
+ *MediaInfo = Atapi_BlkIoDev->DeviceInfo[DeviceIndex]->MediaInfo;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_ReadBlocks
+//
+// Description: ReadBlocks function of EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_ReadBlocks(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer )
+{
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN NumberOfBlocks = 0;
+ UINTN BlockSize = 0;
+ IDE_RECOVERY_BLK_IO_DEV *Atapi_BlkIoDev = NULL;
+
+ if ( This == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Atapi_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ if ( !Atapi_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Atapi_BlkIoDev, EnumerateAtapi );
+ Atapi_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+
+ if ( !Atapi_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia ) {
+ Status = Atapi_GetBlockDeviceMediaInfo( PeiServices, This, DeviceIndex, &MediaInfo );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+ } else {
+ MediaInfo = Atapi_BlkIoDev->DeviceInfo[DeviceIndex]->MediaInfo;
+ }
+
+ BlockSize = MediaInfo.BlockSize;
+
+ if ((BufferSize % BlockSize) != 0 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( !MediaInfo.MediaPresent ) {
+ return EFI_NO_MEDIA;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ Status = Atapi_ReadSectors(
+ Atapi_BlkIoDev->DeviceInfo[DeviceIndex],
+ Buffer,
+ StartLba,
+ NumberOfBlocks,
+ BlockSize
+ );
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_GetNumberOfBlockDevices
+//
+// Description: GetNumberOfBlockDevices function of
+// EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Ata_GetNumberOfBlockDevices(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices )
+{
+ IDE_RECOVERY_BLK_IO_DEV *Ata_BlkIoDev = NULL;
+
+ if ( This == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ata_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( !Ata_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Ata_BlkIoDev, EnumerateAta );
+ Ata_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+ *NumberBlockDevices = Ata_BlkIoDev->DeviceCount;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_GetBlockDeviceMediaInfo
+//
+// Description: GetBlockDeviceMediaInfo function of
+// EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Ata_GetBlockDeviceMediaInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo )
+{
+ IDE_RECOVERY_BLK_IO_DEV *Ata_BlkIoDev = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 *Buffer = NULL;
+ UINT32 SectorOfFirstPartition = 0;
+ UINT16 LowByte = 0, HighByte = 0, BlockSize = 0;
+
+ if ((This == NULL) || (MediaInfo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ata_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( !Ata_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Ata_BlkIoDev, EnumerateAta );
+ Ata_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+
+ if ( DeviceIndex > (Ata_BlkIoDev->DeviceCount - 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( !Ata_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia ) {
+ Ata_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia = TRUE;
+
+ }
+
+ *MediaInfo = Ata_BlkIoDev->DeviceInfo[DeviceIndex]->MediaInfo;
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_ReadBlocks
+//
+// Description: ReadBlocks function of EFI_PEI_RECOVERY_BLOCK_IO_PPI.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Ata_ReadBlocks(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer )
+{
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN NumberOfBlocks = 0;
+ UINTN BlockSize = 0;
+ IDE_RECOVERY_BLK_IO_DEV *Ata_BlkIoDev = NULL;
+
+ if ( This == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ata_BlkIoDev = (IDE_RECOVERY_BLK_IO_DEV*)This;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( BufferSize == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ if ( !Ata_BlkIoDev->HaveEnumeratedDevices ) {
+ EnumerateDevices( Ata_BlkIoDev, EnumerateAta );
+ Ata_BlkIoDev->HaveEnumeratedDevices = TRUE;
+ }
+
+ if ( !Ata_BlkIoDev->DeviceInfo[DeviceIndex]->LookedForMedia ) {
+ Status = Ata_GetBlockDeviceMediaInfo(
+ PeiServices,
+ This,
+ DeviceIndex,
+ &MediaInfo
+ );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+ } else {
+ MediaInfo = Ata_BlkIoDev->DeviceInfo[DeviceIndex]->MediaInfo;
+ }
+
+ BlockSize = MediaInfo.BlockSize;
+
+ if ( BufferSize % BlockSize != 0 ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ( !MediaInfo.MediaPresent ) {
+ return EFI_NO_MEDIA;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if ( StartLba > MediaInfo.LastBlock ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StartLba + NumberOfBlocks) > (MediaInfo.LastBlock + 1)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Ata_ReadSectors(
+ Ata_BlkIoDev->DeviceInfo[DeviceIndex],
+ Buffer,
+ StartLba,
+ NumberOfBlocks,
+ BlockSize
+ );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: EnumerateDevices
+//
+// Description: Enumerates Ata or Atapi devices. Called by
+// Ata_GetNumberOfBlockDevices or
+// Atapi_GetNumberOfBlockDevices.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID EnumerateDevices(
+ IN IDE_RECOVERY_BLK_IO_DEV *IdeRecoveryBlkIoDev,
+ ENUMERATE_TYPE EnumerateType )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 MaxModes = IdeMaxMode;
+ EFI_IDE_MODE Mode = 0;
+ UINT8 Channel = 0;
+ UINT8 Device = 0;
+ UINTN DeviceCount = 0;
+ IDE_RECOVERY_DEVICE_INFO DeviceInfo;
+ UINT8 NativeIdeModeCount = 0;
+
+
+ if ( !gHaveCalledAtaAtapiCommonInit ) {
+ AtaAtapiCommonInit( gPeiServices );
+ gHaveCalledAtaAtapiCommonInit = TRUE;
+ }
+
+ if ( gIdeRecoveryNativeModeSupport ) {
+ //
+ //Based on the number of Nativemode PPI maximum mode support is adjusted
+ //
+ MaxModes = IdeMaxMode + gNativeIdeCount - 1;
+ } else {
+ MaxModes = IdeNative;
+ }
+
+ for ( Mode = IdeLegacy; Mode < MaxModes; Mode++ ) {
+ for ( Channel = IdePrimary; Channel < IdeMaxChannel; Channel++ ) {
+ for ( Device = IdeMaster; Device < IdeMaxDevice; Device++ ) {
+
+ DeviceInfo.Device = Device;
+ if ( Mode == IdeLegacy ) {
+ if ( Channel == IdePrimary ) {
+ DeviceInfo.IdeIoPortRegisters = &PrimaryChannelLegacyIdeIoPortRegisters;
+ } else { //IdeSecondary
+ DeviceInfo.IdeIoPortRegisters = &SecondaryChannelLegacyIdeIoPortRegisters;
+ }
+ } else { //IdeNative
+ if ( Channel == IdePrimary ) {
+ DeviceInfo.IdeIoPortRegisters = &gNativeModePortRegsiters[NativeIdeModeCount];
+ } else { //IdeSecondary
+ DeviceInfo.IdeIoPortRegisters = &gNativeModePortRegsiters[NativeIdeModeCount + 1];
+ }
+ }
+
+ if ( EnumerateType == EnumerateAtapi ) {
+ if ( Atapi_DiscoverDevice( &DeviceInfo )) {
+ Status = (**gPeiServices).AllocatePool( gPeiServices, sizeof(IDE_RECOVERY_DEVICE_INFO), &(IdeRecoveryBlkIoDev->DeviceInfo[DeviceCount]));
+
+ if ( EFI_ERROR( Status )) {
+ return;
+ }
+ DeviceInfo.MediaInfo.MediaPresent = FALSE;
+ DeviceInfo.MediaInfo.LastBlock = 0;
+ DeviceInfo.LookedForMedia = FALSE;
+ *(IdeRecoveryBlkIoDev->DeviceInfo[DeviceCount]) = DeviceInfo;
+ DeviceCount++;
+ }
+ } else {
+ //
+ //EnumerateAta
+ //
+ if ( Ata_DiscoverDevice( &DeviceInfo )) {
+ Status = (**gPeiServices).AllocatePool( gPeiServices, sizeof(IDE_RECOVERY_DEVICE_INFO), &(IdeRecoveryBlkIoDev->DeviceInfo[DeviceCount]));
+
+ if ( EFI_ERROR( Status )) {
+ return;
+ }
+ DeviceInfo.MediaInfo.MediaPresent = TRUE;
+ DeviceInfo.MediaInfo.BlockSize = 0x200;
+ DeviceInfo.LookedForMedia = FALSE;
+ *(IdeRecoveryBlkIoDev->DeviceInfo[DeviceCount]) = DeviceInfo;
+ DeviceCount++;
+ }
+ }
+ }
+ }
+
+ if ( Mode == IdeNative ) {
+ //
+ //index to the Next native mode PPI base address
+ //
+ NativeIdeModeCount = NativeIdeModeCount + 2;
+ }
+ }
+
+ IdeRecoveryBlkIoDev->DeviceCount = DeviceCount;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_DiscoverDevice
+//
+// Description: Called by EnumerateDevices. Looks for ATAPI_SIGNATURE.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN Atapi_DiscoverDevice(
+ IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 Device = DeviceInfo->Device;
+ UINT16 HeadReg = DeviceInfo->IdeIoPortRegisters->Head;
+ UINT16 StatusReg = DeviceInfo->IdeIoPortRegisters->Reg.Status;
+ UINT16 CylinderLsb = DeviceInfo->IdeIoPortRegisters->CylinderLsb;
+ UINT16 CylinderMsb = DeviceInfo->IdeIoPortRegisters->CylinderMsb;
+ UINT8 StatusValue = 0;
+ UINT8 Data8 = 0;
+
+ //
+ // Select Device
+ //
+ IoWrite8( HeadReg, Device << 4 );
+ StatusValue = IoRead8( StatusReg );
+
+ if ((StatusValue == 0x7f) || (StatusValue == 0xff)) {
+ return FALSE;
+ }
+
+ Status = WaitForBSYClear( DeviceInfo->IdeIoPortRegisters, 31000 );
+ StatusValue = IoRead8( StatusReg );
+
+ if ( EFI_ERROR( Status )) {
+ return FALSE;
+ }
+
+ Data8 = IoRead8( CylinderLsb );
+
+ if ( Data8 == (ATAPI_SIGNATURE & 0xff)) {
+ Data8 = IoRead8( CylinderMsb );
+
+ if ( Data8 == (ATAPI_SIGNATURE >> 8)) {
+ Status = Inquiry( DeviceInfo );
+
+ if ( !EFI_ERROR( Status )) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_DiscoverDevice
+//
+// Description: Called by EnumerateDevices. Looks at IDENTIFY data.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN Ata_DiscoverDevice(
+ IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 Device = DeviceInfo->Device;
+ UINT16 HeadReg = DeviceInfo->IdeIoPortRegisters->Head;
+ UINT16 StatusReg = DeviceInfo->IdeIoPortRegisters->Reg.Status;
+ UINT16 CylinderLsb = DeviceInfo->IdeIoPortRegisters->CylinderLsb;
+ UINT16 CylinderMsb = DeviceInfo->IdeIoPortRegisters->CylinderMsb;
+ UINT8 StatusValue = 0;
+ UINT8 Data8 = 0;
+
+ ATA_IDENTIFY_DATA AtaIdentifyData;
+
+
+ //
+ //Select Device
+ //
+ IoWrite8( HeadReg, Device << 4 );
+ StatusValue = IoRead8( StatusReg );
+
+ if ((StatusValue == 0x7f) || (StatusValue == 0xff)) {
+ return FALSE;
+ }
+
+ Status = WaitForBSYClear( DeviceInfo->IdeIoPortRegisters, 31000 );
+ StatusValue = IoRead8( StatusReg );
+
+ if ( EFI_ERROR( Status )) {
+ return FALSE;
+ }
+
+ Data8 = IoRead8( CylinderLsb );
+
+ if ( Data8 == (ATAPI_SIGNATURE & 0xff)) {
+ Data8 = IoRead8( CylinderMsb );
+
+ if ( Data8 == (ATAPI_SIGNATURE >> 8)) {
+ return FALSE;
+ }
+ }
+
+ if ( AtaIdentify( DeviceInfo, &AtaIdentifyData ) == EFI_SUCCESS ) {
+ if ((AtaIdentifyData.GeneralConfiguration_0 & 0x8000) == 0 ) {
+ DeviceInfo->MediaInfo.DeviceType = MaxDeviceType;
+ DeviceInfo->MediaInfo.LastBlock = AtaIdentifyData.TotalUserAddressableSectors_60;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AtapiPacketCommandIn
+//
+// Description: Executes various ATAPI packet commands
+// (TEST_UNIT_READY, INQUIRY, REQUEST_SENSE, READ_CAPACITY, etc).
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtapiPacketCommandIn(
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ IDE_BASE_REGISTERS *IdeIoPortRegisters = DeviceInfo->IdeIoPortRegisters;
+
+ UINT8 Device = DeviceInfo->Device;
+ UINT16 StatusReg = IdeIoPortRegisters->Reg.Status;
+ UINT16 HeadReg = IdeIoPortRegisters->Head;
+ UINT16 CommandReg = IdeIoPortRegisters->Reg.Command;
+ UINT16 FeatureReg = IdeIoPortRegisters->Reg1.Feature;
+ UINT16 CylinderLsbReg = IdeIoPortRegisters->CylinderLsb;
+ UINT16 CylinderMsbReg = IdeIoPortRegisters->CylinderMsb;
+ UINT16 DeviceControlReg = IdeIoPortRegisters->Alt.DeviceControl;
+ UINT16 DataReg = IdeIoPortRegisters->Data;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 Count = 0;
+ UINT16 *CommandIndex = NULL;
+ UINT16 *ptrBuffer = Buffer;
+ UINT32 Index = 0;
+ UINT8 StatusValue = 0;
+ UINT32 WordCount = 0;
+
+ //
+ // required transfer data in word unit.
+ //
+ UINT32 RequiredWordCount = 0;
+
+ //
+ // actual transfer data in word unit.
+ //
+ UINT32 ActualWordCount = 0;
+
+ //
+ // Select device via Device/Head Register.
+ // DEFAULT_CMD: 0xa0 (1010,0000)
+ //
+ IoWrite8( HeadReg, (UINT8) ((Device << 4) | DEFAULT_CMD ));
+
+ //
+ // Set all the command parameters by fill related registers.
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ if ( DRQClear2(
+ DeviceInfo->IdeIoPortRegisters,
+ TIMEOUT
+ ) != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+
+ //
+ // No OVL; No DMA
+ //
+ IoWrite8( FeatureReg, 0x00 );
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
+ // determine how many data should be transfered.
+ //
+ IoWrite8( CylinderLsbReg, (UINT8) ( MAX_ATAPI_BYTE_COUNT & 0x00ff ));
+ IoWrite8( CylinderMsbReg, (UINT8) ( MAX_ATAPI_BYTE_COUNT >> 8 ));
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ IoWrite8( DeviceControlReg, DEFAULT_CTL );
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ IoWrite8( CommandReg, PACKET_CMD );
+
+ Status = DRQReady( IdeIoPortRegisters, TimeoutInMilliSeconds );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+ //
+ // Send out command packet
+ //
+ CommandIndex = Packet->Data16;
+
+ for ( Count = 0; Count < 6; Count++, CommandIndex++ ) {
+ IoWrite16( DataReg, *CommandIndex );
+ gStallPpi->Stall( gPeiServices, gStallPpi, 10 );
+ }
+
+ StatusValue = IoRead8( StatusReg );
+ WaitForBSYClear( IdeIoPortRegisters, LONGTIMEOUT );
+ StatusValue = IoRead8( StatusReg );
+
+ if ((StatusValue & ERR) == ERR ) {
+ //
+ // Trouble! Something's wrong here... Wait some time and return. 3 second is
+ // supposed to be long enough for a device reset latency or error recovery
+ //
+ gStallPpi->Stall( gPeiServices, gStallPpi, 100000 );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( Buffer == NULL || ByteCount == 0 ) {
+ return EFI_SUCCESS;
+ }
+ //
+ // call PioReadWriteData() function to get
+ // requested transfer data form device.
+ //
+ ptrBuffer = Buffer;
+ RequiredWordCount = ByteCount / 2;
+ //
+ // ActuralWordCount means the word count of data really transfered.
+ //
+ ActualWordCount = 0;
+
+ Status = EFI_SUCCESS;
+ while ((Status == EFI_SUCCESS) && (ActualWordCount < RequiredWordCount))
+ {
+ //
+ // before each data transfer stream, the host should poll DRQ bit ready,
+ // which informs device is ready to transfer data.
+ //
+ if ( DRQReady2( IdeIoPortRegisters, TimeoutInMilliSeconds ) != EFI_SUCCESS ) {
+ return CheckErrorStatus( StatusReg );
+ }
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusValue = IoRead8( StatusReg );
+
+ //
+ // get current data transfer size from Cylinder Registers.
+ //
+ WordCount = (( IoRead8( CylinderMsbReg ) << 8) | IoRead8( CylinderLsbReg )) & 0xffff;
+ WordCount /= 2;
+
+ //
+ // perform a series data In/Out.
+ //
+ for ( Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++ )
+ {
+ *ptrBuffer = IoRead16( DataReg );
+
+ ptrBuffer++;
+ }
+
+ if (((GENERIC_CMD*) Packet)->OperationCode_0 == REQUEST_SENSE && ActualWordCount >= 4 ) {
+ RequiredWordCount = EFI_MIN( RequiredWordCount,
+ (UINT32) ( 4 + (((REQUEST_SENSE_DATA*) Buffer)->AdditionalSenseLength_7 / 2))
+ );
+ }
+ }
+ //
+ // After data transfer is completed, normally, DRQ bit should clear.
+ //
+ Status = DRQClear2( IdeIoPortRegisters, TimeoutInMilliSeconds );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // read status register to check whether error happens.
+ //
+ Status = CheckErrorStatus( StatusReg );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Inquiry
+//
+// Description: ATAPI packet command INQUIRY. Uses AtapiPacketCommandIn.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Inquiry(
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ INQUIRY_DATA Idata;
+
+ ZeroMem( &Packet, sizeof (ATAPI_PACKET_COMMAND));
+
+ Packet.Cmd.OperationCode_0 = INQUIRY;
+ Packet.Cmd.AllocationLength_4 = sizeof (INQUIRY_DATA);
+
+ Status = AtapiPacketCommandIn(
+ DeviceInfo,
+ &Packet,
+ (UINT16*)(&Idata),
+ sizeof (INQUIRY_DATA),
+ TIMEOUT
+ );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ( Idata.PeripheralDeviceType_0 == CD_ROM_DEVICE ) {
+ DeviceInfo->MediaInfo.DeviceType = IdeCDROM;
+ DeviceInfo->MediaInfo.MediaPresent = FALSE;
+ DeviceInfo->MediaInfo.LastBlock = 0;
+ DeviceInfo->MediaInfo.BlockSize = 0x800;
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_DetectMedia
+//
+// Description:
+// -Loop: Issues ATAPI packet command TEST_UNIT_READY.
+// If this is not successful, then look at SENSE data.
+// If you get the sense data for (1) becoming ready, (2) media
+// changed, or (3) power on reset, then stall for some time and
+// continue looping with TEST_UNIT_READY and REQUEST_SENSE.
+// -If TEST_UNIT_READY is successful, then issue READ_CAPACITY
+// packet command, which should get device info.
+// -If TEST_UNIT_READY is not succesful or if the SENSE data
+// contains some other error (not one of the three listed above),
+// then return an error.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_DetectMedia(
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ UINTN Index = 0;
+ REQUEST_SENSE_DATA SenseBuffers[MAX_SENSE_KEY_COUNT];
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT8 SenseCounts = 0;
+ BOOLEAN DeviceIsReady = FALSE;
+
+ DeviceInfo->MediaInfo.MediaPresent = FALSE;
+ DeviceInfo->MediaInfo.LastBlock = 0;
+
+ DeviceIsReady = FALSE;
+
+ for ( Index = 0; Index < 50; Index++ ) {
+ Status = TestUnitReady( DeviceInfo );
+
+ if ( Status == EFI_SUCCESS ) {
+ DeviceIsReady = TRUE;
+ break;
+ }
+
+ SenseCounts = MAX_SENSE_KEY_COUNT;
+ Status = RequestSense( DeviceInfo, SenseBuffers, &SenseCounts );
+
+ if ( SenseCounts == 0 ) {
+ gStallPpi->Stall( gPeiServices, gStallPpi, 250000 );
+ continue;
+ }
+
+ if (((SenseBuffers[0].SenseKey_2 == SK_NOT_READY) && (SenseBuffers[0].AdditionalSenseCode_12 == 4) && (SenseBuffers[0].AdditionalSenseCodeQualifier_13 == 1)) // Becoming ready
+ || ((SenseBuffers[0].SenseKey_2 == SK_UNIT_ATTENTION) && (SenseBuffers[0].AdditionalSenseCode_12 == 0x28) && (SenseBuffers[0].AdditionalSenseCodeQualifier_13 == 0)) // Media Changed
+ || ((SenseBuffers[0].SenseKey_2 == SK_UNIT_ATTENTION) && (SenseBuffers[0].AdditionalSenseCode_12 == 0x29) && (SenseBuffers[0].AdditionalSenseCodeQualifier_13 == 0))) { // Power on Reset
+ gStallPpi->Stall( gPeiServices, gStallPpi, 250000 );
+ } else {
+ break;
+ }
+ }
+
+ if ( DeviceIsReady ) {
+ Status = ReadCapacity( DeviceInfo );
+ return Status;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: TestUnitReady
+//
+// Description: ATAPI command TEST_UINT_READY. Uses AtapiPacketCommandIn.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS TestUnitReady(
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+
+ ZeroMem( &Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Cmd.OperationCode_0 = TEST_UNIT_READY;
+
+ Status = AtapiPacketCommandIn( DeviceInfo, &Packet, NULL, 0, TIMEOUT );
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: RequestSense
+//
+// Description: Send Request sense command
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RequestSense(
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ IN REQUEST_SENSE_DATA *SenseBuffers,
+ IN OUT UINT8 *SenseCounts )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ REQUEST_SENSE_DATA *Sense = SenseBuffers;
+ ATAPI_PACKET_COMMAND Packet;
+
+ ZeroMem( SenseBuffers, sizeof (REQUEST_SENSE_DATA) * (*SenseCounts));
+
+ ZeroMem( &Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Cmd.OperationCode_0 = REQUEST_SENSE;
+ Packet.Cmd.AllocationLength_4 = sizeof (REQUEST_SENSE_DATA);
+
+ *SenseCounts = 0;
+
+ while ( TRUE ) {
+ Status = AtapiPacketCommandIn(
+ DeviceInfo,
+ &Packet,
+ (UINT16*) Sense,
+ sizeof (REQUEST_SENSE_DATA),
+ TIMEOUT
+ );
+
+ if ( Status != EFI_SUCCESS ) {
+ if ( *SenseCounts == 0 ) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ (*SenseCounts)++;
+
+ if ( *SenseCounts == MAX_SENSE_KEY_COUNT ) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // We limit MAX sense data count to 20 in order to avoid dead loop. Some
+ // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
+ // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
+ // supposed to be large enough for any ATAPI device.
+ // (Actually 6, not 20).
+ if ( Sense->SenseKey_2 != SK_NO_SENSE ) {
+ Sense++;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadCapacity
+//
+// Description: ATAPI packet command READ_CAPACITY.
+// Uses AtapiPacketCommandIn.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS ReadCapacity(
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo )
+{
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ READ_CAPACITY_DATA Data;
+
+ ZeroMem( &Data, sizeof (Data));
+
+ if ( DeviceInfo->MediaInfo.DeviceType == IdeCDROM ) {
+ ZeroMem( &Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Cmd.OperationCode_0 = READ_CAPACITY;
+ Status = AtapiPacketCommandIn(
+ DeviceInfo,
+ &Packet,
+ (UINT16*)(&Data),
+ sizeof (READ_CAPACITY_DATA),
+ LONGTIMEOUT
+ );
+
+ if ( Status == EFI_SUCCESS ) {
+ if ( DeviceInfo->MediaInfo.DeviceType == IdeCDROM ) {
+ DeviceInfo->MediaInfo.LastBlock = (Data.LastLba0 << 24) | (Data.LastLba1 << 16) | (Data.LastLba2 << 8) | Data.LastLba3;
+ DeviceInfo->MediaInfo.MediaPresent = TRUE;
+ DeviceInfo->MediaInfo.BlockSize = 0x800;
+ }
+ return EFI_SUCCESS;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Atapi_ReadSectors
+//
+// Description: Helper function called by Atapi_ReadBlocks.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Atapi_ReadSectors(
+ IN OUT IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ IN VOID *Buffer,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN UINTN BlockSize )
+{
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BlocksRemaining = 0;
+ UINT32 Lba32 = 0;
+ UINT32 ByteCount = 0;
+ UINT16 SectorCount = 0;
+ VOID *ptrBuffer = NULL;
+ UINT16 MaxBlock = 0;
+
+ ZeroMem( &Packet, sizeof (ATAPI_PACKET_COMMAND));
+
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) StartLba;
+ ptrBuffer = Buffer;
+
+ //
+ // limit the data bytes that can be transfered by one Read(10) Command
+ //
+ MaxBlock = (UINT16) ( 0x10000 / BlockSize );
+ //
+ // (64k bytes)
+ //
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while ( BlocksRemaining > 0 ) {
+ if ( BlocksRemaining <= MaxBlock ) {
+ SectorCount = (UINT16) BlocksRemaining;
+ } else {
+ SectorCount = MaxBlock;
+ }
+
+ Read10Packet->OperationCode_0 = READ_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) ( Lba32 & 0xff );
+ Read10Packet->Lba2 = (UINT8) ( Lba32 >> 8 );
+ Read10Packet->Lba1 = (UINT8) ( Lba32 >> 16 );
+ Read10Packet->Lba0 = (UINT8) ( Lba32 >> 24 );
+
+ //
+ // TransferLengthMSB ~ TransferLengthLSB specify the transfer length in block unit.
+ //
+ Read10Packet->TransferLengthLSB = (UINT8) ( SectorCount & 0xff );
+ Read10Packet->TransferLengthMSB = (UINT8) ( SectorCount >> 8 );
+
+ ByteCount = (UINT32) ( SectorCount * BlockSize );
+
+ Status = AtapiPacketCommandIn(
+ DeviceInfo,
+ &Packet,
+ (UINT16*) ptrBuffer,
+ ByteCount,
+ LONGTIMEOUT
+ );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8*) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AtaPioDataIn
+//
+// Description: Does ATA protocol Pio In with data.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaPioDataIn(
+ IN IDE_BASE_REGISTERS *IdeIoPortRegisters,
+ OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb,
+ IN UINT8 Device,
+ IN UINT8 Command )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ UINT16 HeadReg = IdeIoPortRegisters->Head;
+ UINT16 SectorCountReg = IdeIoPortRegisters->SectorCount;
+ UINT16 SectorNumberReg = IdeIoPortRegisters->SectorNumber;
+ UINT16 CylinderLsbReg = IdeIoPortRegisters->CylinderLsb;
+ UINT16 CylinderMsbReg = IdeIoPortRegisters->CylinderMsb;
+ UINT16 CommandReg = IdeIoPortRegisters->Reg.Command;
+ UINT16 AltStatusRegister = IdeIoPortRegisters->Alt.AltStatus;
+ UINT16 StatusReg = IdeIoPortRegisters->Reg.Status;
+ UINT16 DataReg = IdeIoPortRegisters->Data;
+
+ UINT32 WordCount = 0;
+ UINT32 Increment = 0;
+ UINT32 Index = 0;
+ UINT16 *Buffer16 = (UINT16*)Buffer;
+ ;
+
+ IoWrite8( HeadReg, Device );
+
+ Status = WaitForBSYClear( IdeIoPortRegisters, TIMEOUT );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = DRQClear2( IdeIoPortRegisters, TIMEOUT );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = DRQClear2( IdeIoPortRegisters, TIMEOUT );
+
+ if ( Status != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ IoWrite8( SectorCountReg, SectorCount );
+ IoWrite8( SectorNumberReg, SectorNumber );
+ IoWrite8( CylinderLsbReg, CylinderLsb );
+ IoWrite8( CylinderMsbReg, CylinderMsb );
+
+ IoWrite8( CommandReg, Command );
+
+ IoRead8( AltStatusRegister );
+
+ Increment = 256;
+ WordCount = 0;
+
+ while ( WordCount < ByteCount / 2 ) {
+ Status = DRQReady2( IdeIoPortRegisters, COMMAND_COMPLETE_TIMEOUT );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+
+ if ( CheckErrorStatus( StatusReg ) != EFI_SUCCESS ) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((WordCount + Increment) > ByteCount / 2 ) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ for ( Index = 0; Index < Increment; Index++ )
+ {
+ *Buffer16++ = IoRead16( DataReg );
+ }
+
+ WordCount += Increment;
+ }
+
+ Status = DRQClear( IdeIoPortRegisters, TIMEOUT );
+
+ if ( Status != EFI_SUCCESS ) {
+ return CheckErrorStatus( StatusReg );
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AtaIdentify
+//
+// Description: ATA Identify command. Uses AtaPioDataIn
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AtaIdentify(
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ OUT ATA_IDENTIFY_DATA *AtaIdentifyData )
+{
+ return AtaPioDataIn( DeviceInfo->IdeIoPortRegisters,
+ AtaIdentifyData,
+ sizeof (ATA_IDENTIFY_DATA),
+ 0,
+ 0,
+ 0,
+ 0,
+ DeviceInfo->Device << 4,
+ ATA_IDENTIFY_DEVICE_CMD
+ );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: Ata_ReadSectors
+//
+// Description: Helper function called by Ata_ReadBlocks.
+//
+// Input:
+// IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo - pointer to the device info structure
+// IN OUT VOID *Buffer - Pointer to a buffer that will hold the Data that is read
+// IN EFI_PEI_LBA StartLba - the first LBA to read
+// IN UINTN NumberOfBlocks - total number of blocks to read
+// IN UINTN BlockSize - size of the blocks to be read
+//
+// Output:
+// EFI_SUCCESS - Read happened correctly
+// OTHER - any valid error from AtaPioDataIn()
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Ata_ReadSectors(
+ IN IDE_RECOVERY_DEVICE_INFO *DeviceInfo,
+ IN OUT VOID *Buffer,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN NumberOfBlocks,
+ IN UINTN BlockSize )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN BlocksRemaining = 0;
+ UINT32 Lba32 = 0;
+ UINT8 LbaLow = 0;
+ UINT8 LbaMid = 0;
+ UINT8 LbaHigh = 0;
+ UINT32 ByteCount = 0;
+ UINT16 SectorCount = 0;
+ VOID *ptrBuffer = NULL;
+ UINT16 MaxBlock = 0;
+ UINT8 Dev = 0;
+ UINT8 Device = 0;
+
+ Lba32 = (UINT32) StartLba;
+ ptrBuffer = Buffer;
+
+ MaxBlock = (UINT16) ( 0x20000 / BlockSize );
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ Dev = (DeviceInfo->Device << 4) | LBA_MODE;
+ while ( BlocksRemaining > 0 ) {
+ if ( BlocksRemaining < MaxBlock ) {
+ SectorCount = BlocksRemaining;
+ } else {
+ SectorCount = MaxBlock;
+ }
+ LbaLow = (UINT8) ( Lba32 & 0xff );
+ LbaMid = (UINT8) ( Lba32 >> 8 );
+ LbaHigh = (UINT8) ( Lba32 >> 16 );
+
+ ByteCount = (UINT32) ( SectorCount * BlockSize );
+
+ Dev |= (Lba32 >> 24);
+ Status = AtaPioDataIn( DeviceInfo->IdeIoPortRegisters,
+ ptrBuffer,
+ ByteCount,
+ (UINT8) SectorCount, //sector count
+ LbaLow, //sector number
+ LbaMid, //lsb
+ LbaHigh, //msb
+ Dev,
+ ATA_READ_SECTOR_CMD
+ );
+
+ if ( Status != EFI_SUCCESS ) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8*) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: WaitForBitsToClear
+//
+// Description: Helper functin used by WaitForBSYClear, DRQClear, DRQClear2.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitForBitsToClear(
+ UINT16 Register,
+ UINT8 Bits,
+ UINTN TimeoutInMilliSeconds )
+{
+ UINTN Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
+ UINT8 StatusValue = 0;
+
+ do {
+ StatusValue = IoRead8( Register );
+
+ if ((StatusValue & Bits) == 0x00 ) {
+ break;
+ }
+
+ gStallPpi->Stall( gPeiServices, gStallPpi, 250 );
+
+ Delay--;
+ } while ( Delay );
+
+ if ( Delay == 0 ) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: WaitForBSYClear
+//
+// Description: Wait for busy bit to clear
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS WaitForBSYClear(
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ return WaitForBitsToClear( IdeIoRegisters->Reg.Status, BSY, TimeoutInMilliSeconds );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DRQClear
+//
+// Description: Wait for the DRQ bit clear
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DRQClear(
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ return WaitForBitsToClear( IdeIoRegisters->Reg.Status, DRQ | BSY, TimeoutInMilliSeconds );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DRQClear2
+//
+// Description: Wait for the DRQ bit clear in Alternate Status Reg
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DRQClear2(
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ return WaitForBitsToClear( IdeIoRegisters->Alt.AltStatus, DRQ | BSY, TimeoutInMilliSeconds );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DRQReadyHelper
+//
+// Description:
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DRQReadyHelper(
+ UINT16 StatusRegister,
+ UINT16 ErrorRegister,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ UINTN Delay = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
+ UINT8 StatusValue = 0;
+ UINT8 ErrValue = 0;
+
+ do
+ {
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusValue = IoRead8( StatusRegister );
+
+ //
+ // BSY==0,DRQ==1
+ //
+ if ((StatusValue & (BSY | DRQ)) == DRQ ) {
+ break;
+ }
+
+ if ((StatusValue & (BSY | ERR)) == ERR ) {
+ ErrValue = IoRead8( ErrorRegister );
+
+ if ((ErrValue & ABRT_ERR) == ABRT_ERR ) {
+ return EFI_ABORTED;
+ }
+ }
+
+ gStallPpi->Stall( gPeiServices, gStallPpi, 250 );
+
+ Delay--;
+ } while ( Delay );
+
+ if ( Delay == 0 ) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DRQReady
+//
+// Description: Wait for the DRQ ready
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DRQReady(
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ return DRQReadyHelper( IdeIoRegisters->Reg.Status, IdeIoRegisters->Reg1.Error, TimeoutInMilliSeconds );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: DRQReady2
+//
+// Description: Wait for the DRQ Ready in Alternate Status Reg
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS DRQReady2(
+ IN IDE_BASE_REGISTERS *IdeIoRegisters,
+ IN UINTN TimeoutInMilliSeconds )
+{
+ return DRQReadyHelper( IdeIoRegisters->Alt.AltStatus, IdeIoRegisters->Reg1.Error, TimeoutInMilliSeconds );
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: CheckErrorStatus
+//
+// Description: Check for the Errros.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CheckErrorStatus(
+ IN UINT16 StatusReg )
+{
+ UINT8 StatusValue = IoRead8( StatusReg );
+
+ if ((StatusValue & (ERR | DWF | CORR)) == 0 ) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ZeroMem
+//
+// Description: Clear the Memory
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static
+VOID ZeroMem(
+ IN VOID *Buffer,
+ IN UINTN Size )
+{
+ UINT8 *ptr;
+
+ ptr = Buffer;
+ while ( Size-- )
+ {
+ *(ptr++) = 0;
+ }
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2011, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/ReFlash/Esrt.c b/Core/EM/Recovery/ReFlash/Esrt.c
new file mode 100644
index 0000000..1823328
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/Esrt.c
@@ -0,0 +1,415 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/Esrt.c 1 3/21/13 7:25a Thomaschen $
+//
+// $Revision: 1 $
+//
+// $Date: 3/21/13 7:25a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/Esrt.c $
+//
+// 1 3/21/13 7:25a Thomaschen
+//
+// 6 2/27/13 3:54p Artems
+// [TAG] EIP106722
+// [Category] Improvement
+// [Description] Used different GUID to differentiate between AMI and
+// Win8 firmware update
+// [Files] Esrt.c
+//
+// 5 2/07/13 5:26p Artems
+// [TAG] EIP106722
+// [Category] Improvement
+// [Description] Add creation of firmware update version from FID table
+// [Files] Esrt.c
+//
+// 4 2/05/13 1:41p Artems
+// [TAG] EIP111562
+// [Category] Improvement
+// [Description] Add Enable/Disable support for Windows8-style firmware
+// update
+// [Files] Esrt.c Reflash.c Reflash.sdl
+//
+// 3 1/02/13 12:18p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Flash update progress report changes:
+// - report progress in non-interactive flash update
+// - do not report progress in Win8-style flash update
+// [Files] ReflashWorker.c Reflash.h Esrt.c
+//
+// 2 8/02/12 11:59a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c
+//
+// 1 7/20/12 10:20a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support for Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Esrt.c
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+
+#include <AmiHobs.h>
+#include <AmiDxeLib.h>
+#include <Capsule.h>
+#include <Setup.h>
+#include <PPI/FwVersion.h>
+#include <Protocol/AmiReflashProtocol.h>
+#include <Protocol/FirmwareVolume2.h>
+#include "Reflash.h"
+
+#define MAX_ESRT_ENTRIES 1
+
+#define FW_TYPE_UNKNOWN 0
+#define FW_TYPE_SYSTEM_FIRMWARE 1
+#define FW_TYPE_DEVICE_FIRMWARE 2
+#define FW_TYPE_FIRMWARE_DRIVER 3
+
+#define FW_UPDATE_STATUS_SUCCESS 0
+#define FW_UPDATE_STATUS_UNKNOWN_ERROR 1
+#define FW_UPDATE_STATUS_OUT_OF_RESOURCES 2
+#define FW_UPDATE_STATUS_INCORRECT_VERSION 3
+#define FW_UPDATE_STATUS_INVALID_FORMAT 4
+#define FW_UPDATE_STATUS_AUTHENTICATION_ERROR 5
+
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID \
+ { 0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 }
+
+#define FID_FFS_FILE_NAME_GUID \
+ { 0x3fd1d3a2, 0x99f7, 0x420b, 0xbc, 0x69, 0x8b, 0xb1, 0xd4, 0x92, 0xa3, 0x32 }
+
+#define FID_FFS_FILE_SECTION_GUID \
+ { 0x2EBE0275, 0x6458, 0x4AF9, 0x91, 0xED, 0xD3, 0xF4, 0xED, 0xB1, 0x00, 0xAA }
+
+#pragma pack(push, 1)
+typedef struct _FIRMWARE_RESOURCE_ENTRY {
+ EFI_GUID FwClass;
+ UINT32 FwType;
+ UINT32 FwVersion;
+ UINT32 LowestSupportedFwVersion;
+ UINT32 CapsuleFlags;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+} FIRMWARE_RESOURCE_ENTRY;
+
+typedef struct _EFI_ESRT_TABLE {
+ UINT32 FwResourceCount;
+ UINT32 FwMaxResources;
+ UINT64 FwResourceVersion;
+ FIRMWARE_RESOURCE_ENTRY Entries[MAX_ESRT_ENTRIES];
+} EFI_ESRT_TABLE;
+
+#pragma pack(pop)
+
+static EFI_GUID SystemFirmwareUpdateClass = W8_FW_UPDATE_IMAGE_CAPSULE_GUID;
+static EFI_GUID SystemResourceTableGuid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+static EFI_GUID guidHob = HOB_LIST_GUID;
+static W8_IMAGE_CAPSULE *Image;
+
+static const UINT32 FidSignature = 0x44494624; //$FID
+
+EFI_STATUS GetDisplayImage(
+ IN EFI_REFLASH_PROTOCOL *This,
+ OUT UINTN *CoordinateX,
+ OUT UINTN *CoordinateY,
+ OUT VOID **ImageAddress
+);
+
+EFI_STATUS FwUpdate(
+ IN EFI_REFLASH_PROTOCOL *This
+);
+
+EFI_REFLASH_PROTOCOL AmiReflashProtocol = {
+ FwUpdate,
+ GetDisplayImage
+};
+
+EFI_STATUS GetFidFromFv(
+ OUT VOID *Fid
+)
+{
+ static EFI_GUID FidFileName = FID_FFS_FILE_NAME_GUID;
+ EFI_STATUS Status;
+ EFI_HANDLE *FvHandle;
+ UINTN FvCount;
+ UINTN i;
+ UINTN BufferSize;
+ VOID *Buffer;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &FvCount, &FvHandle);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ for(i = 0; i < FvCount; i++)
+ {
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 AuthStatus;
+ Status = pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ if (EFI_ERROR(Status))
+ continue;
+ Buffer = 0;
+ BufferSize = 0;
+ Status = Fv->ReadSection(Fv, &FidFileName, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 0, &Buffer, &BufferSize, &AuthStatus);
+ TRACE((-1, "extracted section with guid %g\n", (EFI_GUID *)Buffer));
+ if (!EFI_ERROR(Status)) {
+ (UINT8 *)Buffer += sizeof(EFI_GUID);
+ MemCpy(Fid, Buffer, sizeof(FW_VERSION));
+ (UINT8 *)Buffer -= sizeof(EFI_GUID);
+ pBS->FreePool(Buffer);
+ return EFI_SUCCESS;
+ }
+ }
+ pBS->FreePool(FvHandle);
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS GetFidFromBuffer(
+ IN VOID *Buffer,
+ OUT VOID *Fid
+)
+{
+ static EFI_GUID FidSectionGuid = FID_FFS_FILE_SECTION_GUID;
+ UINT32 Signature;
+ UINT32 *SearchPointer;
+ UINT32 *FidPointer;
+
+ SearchPointer = (UINT32 *)((UINT8 *)Buffer - sizeof(EFI_GUID) + FLASH_SIZE);
+ Signature = FidSectionGuid.Data1;
+
+ do {
+ if(*SearchPointer == Signature) {
+ if(!guidcmp(&FidSectionGuid, (EFI_GUID *)SearchPointer)) {
+ FidPointer = (UINT32 *)((EFI_GUID *)SearchPointer + 1);
+ if(*FidPointer == FidSignature) {
+ MemCpy(Fid, FidPointer, sizeof(FW_VERSION));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while(SearchPointer-- >= (UINT32 *)Buffer);
+
+ return EFI_NOT_FOUND;
+}
+
+UINT32 GetVersionFromFid(
+ VOID *Image OPTIONAL
+)
+{
+ FW_VERSION Fid;
+ UINT32 Version;
+ EFI_STATUS Status;
+
+ if(Image == NULL)
+ Status = GetFidFromFv(&Fid);
+ else
+ Status = GetFidFromBuffer(Image, &Fid);
+
+ if(EFI_ERROR(Status))
+ return 0;
+
+ Version = Atoi(Fid.ProjectMajorVersion);
+ Version <<= 16;
+ Version += Atoi(Fid.ProjectMinorVersion);
+ return Version;
+}
+
+EFI_STATUS InstallEsrtTable(
+ VOID
+)
+{
+ static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ EFI_STATUS Status;
+ UINTN Size = sizeof(UINT32);
+ UINT32 Version;
+ EFI_ESRT_TABLE *EsrtTable;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, sizeof(EFI_ESRT_TABLE), &EsrtTable);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ EsrtTable->FwResourceCount = 1;
+ EsrtTable->FwMaxResources = MAX_ESRT_ENTRIES;
+ EsrtTable->FwResourceVersion = 1;
+
+ EsrtTable->Entries[0].FwClass = SystemFirmwareUpdateClass;
+ EsrtTable->Entries[0].FwType = FW_TYPE_SYSTEM_FIRMWARE;
+ EsrtTable->Entries[0].FwVersion = GetVersionFromFid(NULL);
+ EsrtTable->Entries[0].LowestSupportedFwVersion = EsrtTable->Entries[0].FwVersion; //no rollback allowed
+ EsrtTable->Entries[0].CapsuleFlags = 0;
+
+ Status = pRS->GetVariable(FW_VERSION_VARIABLE, &gAmiGlobalVariableGuid, NULL, &Size, &Version);
+ if(!EFI_ERROR(Status)) {
+ EsrtTable->Entries[0].LastAttemptVersion = Version;
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ } else {
+ pHit = GetEfiConfigurationTable(pST, &guidHob);
+ if(pHit != NULL && !EFI_ERROR(FindNextHobByGuid(&RecoveryHobGuid, &pHit))) {
+ EsrtTable->Entries[0].LastAttemptVersion = GetVersionFromFid((VOID *)(UINTN)((RECOVERY_IMAGE_HOB*)pHit)->Address);
+ switch(((RECOVERY_IMAGE_HOB*)pHit)->FailedStage) {
+ case 0: //no authentication/verification error
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ break;
+ case 1:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_INVALID_FORMAT;
+ break;
+ case 2:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_AUTHENTICATION_ERROR;
+ break;
+ case 3:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_AUTHENTICATION_ERROR;
+ break;
+ case 4:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_INCORRECT_VERSION;
+ break;
+ default:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ break;
+ }
+ } else { //recovery hob not found - regular boot
+ EsrtTable->Entries[0].LastAttemptVersion = EsrtTable->Entries[0].FwVersion;
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_SUCCESS;
+ }
+ }
+
+ Status = pBS->InstallConfigurationTable(&SystemResourceTableGuid, EsrtTable);
+ return Status;
+}
+
+EFI_STATUS IsWin8Update(
+ BOOLEAN RecoveryFailed
+)
+{
+ AMI_CAPSULE_HOB *Hob;
+ static EFI_GUID AmiCapsuleHobGuid = AMI_CAPSULE_HOB_GUID;
+ static EFI_GUID ImageCapsuleGuid = W8_SCREEN_IMAGE_CAPSULE_GUID;
+ static EFI_GUID guidBootFlow = BOOT_FLOW_VARIABLE_GUID;
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+ UINT32 BootFlow = BOOT_FLOW_CONDITION_OS_UPD_CAP;
+
+ Hob = GetEfiConfigurationTable(pST, &guidHob);
+ if(Hob == NULL)
+ return EFI_NOT_FOUND;
+
+ do {
+ Status = FindNextHobByGuid(&AmiCapsuleHobGuid, &Hob);
+ if(!EFI_ERROR(Status) && !guidcmp(&(Hob->CapsuleGuid), &ImageCapsuleGuid))
+ break;
+ } while(!EFI_ERROR(Status));
+
+ if(EFI_ERROR(Status)) //no image hob - we're not on OS FW update path
+ return Status;
+
+ if(RecoveryFailed) { //we're on OS FW update path, but recovery can't be performed
+ InstallEsrtTable();
+ return EFI_UNLOAD_IMAGE;
+ }
+
+//save image capsule pointer
+ Image = (W8_IMAGE_CAPSULE *)(VOID *)(UINTN)(Hob->CapsuleData);
+//install reflash protocol
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gAmiReflashProtocolGuid,
+ &AmiReflashProtocol,
+ NULL);
+ if(EFI_ERROR(Status))
+ return Status;
+
+//set boot flow
+ pRS->SetVariable(L"BootFlow", &guidBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow);
+ return Status;
+}
+
+EFI_STATUS GetDisplayImage(
+ IN EFI_REFLASH_PROTOCOL *This,
+ OUT UINTN *CoordinateX,
+ OUT UINTN *CoordinateY,
+ OUT VOID **ImageAddress
+)
+{
+ if(CoordinateX == NULL ||
+ CoordinateY == NULL ||
+ ImageAddress == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ *CoordinateX = Image->ImageOffsetX;
+ *CoordinateY = Image->ImageOffsetY;
+ *ImageAddress = Image->Image;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS FwUpdate(
+ IN EFI_REFLASH_PROTOCOL *This
+)
+{
+ EFI_STATUS Status;
+ UINT32 Version;
+
+/* set version we're upgrading to */
+ Version = GetVersionFromFid(RecoveryBuffer);
+ Status = pRS->SetVariable(FW_VERSION_VARIABLE, &gAmiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(UINT32), &Version);
+
+ Status = Prologue(FALSE, TRUE);
+ if(EFI_ERROR(Status))
+ pRS->ResetSystem(EfiResetCold, Status, 0, NULL);
+
+ Status = FlashWalker(FALSE);
+ if(EFI_ERROR(Status))
+ pRS->ResetSystem(EfiResetCold, Status, 0, NULL);
+
+ Status = Epilogue();
+ return Status;
+}
+
+#endif // #if SUPPORT_WIN8_STYLE_FW_UPDATE
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.c b/Core/EM/Recovery/ReFlash/ReFlash.c
new file mode 100644
index 0000000..773d7f9
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.c
@@ -0,0 +1,601 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlash.c 3 10/01/13 2:03a Thomaschen $
+//
+// $Revision: 3 $
+//
+// $Date: 10/01/13 2:03a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlash.c $
+//
+// 3 10/01/13 2:03a Thomaschen
+// Update for EIP137328.
+//
+// 2 4/16/13 5:48a Thomaschen
+// Fixed for EIP106722.
+//
+//
+// 40 2/11/13 3:41p Artems
+// [TAG] EIP112180
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] In non-interactive mode system updated flash even when
+// there is no valid image
+// [RootCause] In non-interactive mode system didn't check flash image
+// validity
+// [Solution] Added check of flash image validity. Inform user if image
+// is invalid or not found
+// [Files] Reflash.c ReflashWorker.c Reflash.uni Reflash.vfr
+//
+// 39 2/05/13 1:41p Artems
+// [TAG] EIP111562
+// [Category] Improvement
+// [Description] Add Enable/Disable support for Windows8-style firmware
+// update
+// [Files] Esrt.c Reflash.c Reflash.sdl
+//
+// 38 7/20/12 10:17a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+// 37 5/22/12 4:54p Artems
+// [TAG] EIP88314
+// [Category] Improvement
+// [Description] Recovery takes a long time for large flash size
+// Rewrite reflash code to not give control back to TSE until finished
+// reporting progress via DisplayProgress API of AMI Post manager
+// [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+// Reflash.uni
+//
+// 36 4/09/12 6:03p Artems
+// Undo previous change
+//
+// 35 2/08/12 4:27a Nerofan
+// Update it for capsule function if memory size is over 2G.
+//
+// 34 12/05/11 1:49p Artems
+// EIP 74623: Add capabilities similar to ones in SMIFlash module
+//
+// 33 11/14/11 4:07p Artems
+// Fixed bug with hob size comparison
+// Set default attributes for Reflash Setup variable
+//
+// 32 11/14/11 3:18p Artems
+// Defined Extended errors for security recovery capsule check
+//
+// 31 11/12/11 6:48p Artems
+// Added fault tolerant recovery support
+//
+// 30 11/02/11 4:54p Artems
+// EIP 74446: Fixed bug - reflash is enabled when recovery image is not
+// found
+//
+// 29 5/13/11 4:51p Artems
+// Added secure flash recovery/update support. Extended error reporting
+// Added handling of unsupported FormBrowser actions
+//
+// 28 5/05/11 2:00p Artems
+// Bugfix: callback supports only "CHANGING" browser action
+//
+// 27 5/04/11 5:54p Artems
+// Bugfix: function FlashProgress output parameter ActionRequest was
+// undefined
+//
+// 26 11/17/10 2:52p Felixp
+// Enhencement (EIP 36355):
+// The Reflash component is updated to be extensible with external
+// eModules.
+// The eModules can contribute content for the Recovery setup page,
+// and provide callback function that will be periodically called
+// once BIOS update is completed.The external eModules can be used
+// to implement update of non-standard firmware components.
+// For example, update of the non-shared EC firmware.
+//
+// 25 10/07/10 11:02a Felixp
+// FlashDeviceWriteEnable/FlashDeviceWriteDisable calls added.
+//
+// 24 10/01/10 2:14p Felixp
+// Previous changes related to descrete EC firmware update are rolled back
+// for the Core labeling.
+//
+// 22 12/24/09 12:42p Oleksiyy
+// EIP 30173: Support for the EC Firmware Area Update control added. Main
+// token to enable this support is EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+// should be located in specific EC-related .sdl file.
+//
+// 21 11/25/09 11:38a Felixp
+//
+// 20 11/25/09 11:27a Felixp
+// Action parameter of the Callback function is updated based on UEFI
+// errata
+//
+// 19 10/09/09 6:30p Felixp
+// ReFlash component is updated to support Framework and UEFI 2.1 HII
+//
+// 18 8/25/09 5:29p Felixp
+// Recovery module is updated to pass recovery image location via special
+// GUIDed HOB.
+// Old implementation that was relying on Firmware Volume (FV) handle,
+// required porting for a projects with non standard FV management policy.
+//
+// 17 7/09/09 5:59p Oleksiyy
+// Files clean-up, some headers added
+//
+// 16 5/21/09 4:44p Felixp
+// ReFlash driver is updated to use FlashProtocol instead of Flash library
+// functions.
+//
+// 15 1/02/09 1:14p Felixp
+// Bug fix: initialize size before call to GetVariable
+//
+// 14 10/10/08 5:30p Felixp
+//
+// 13 3/12/08 2:55p Felixp
+// Error code reporting when flash update failed added
+//
+// 12 10/19/07 6:23p Felixp
+// Recovery Flash Update module extended to support Boot Block update.
+// Boot block update can be enabled or disabled using SDL token.
+// In addition to that there is an SDL token that enables/disables
+// checkbox on the
+// recovery setup page that user can use to enable or disable boot block
+// update.
+//
+// 11 4/13/07 6:07p Ambikas
+// Coding standard changes: updated the year in the AMI copyright
+// header/footer.
+//
+// 10 1/26/07 10:31a Anandakrishnanl
+// Added Flash Device Write Enabling and Disabling code to make the device
+// Write wnable before Flash Block writes.
+//
+// 9 12/29/06 2:58p Felixp
+// Updated to use new Flash Interface
+//
+// 8 12/22/06 9:38a Felixp
+// Support for optional NVRAM reset based on user input added
+//
+// 7 12/20/06 1:36p Felixp
+//
+// 6 10/30/06 5:44p Felixp
+// Updated to be complient with HII Spec. 0.92 (used to be 0.91)
+//
+// 5 10/27/06 11:48a Felixp
+// Flash related external variables from Tokens.c are used (instead of
+// global variables declared in Reflash.c)
+//
+// 4 8/24/06 9:19a Felixp
+// x64 Support
+//
+// 3 4/12/06 5:49p Felixp
+//
+// 2 3/13/06 1:47a Felixp
+//
+// 1 12/01/05 9:35a Felixp
+//
+// 1 11/08/05 4:04a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlash.c
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <HOB.h>
+#include <Flash.h>
+#include <AmiCspLib.h>
+#include <AmiHobs.h>
+#include "ReFlash.h"
+
+
+static EFI_GUID guidRecovery = RECOVERY_FORM_SET_GUID;
+EFI_HANDLE ThisImageHandle;
+FLASH_PROTOCOL *Flash;
+EFI_HII_HANDLE ReflashHiiHandle = NULL;
+UINT8 *RecoveryBuffer = NULL;
+EFI_STATUS RecoveryStatus = EFI_SUCCESS;
+
+
+EFI_HII_CONFIG_ACCESS_PROTOCOL CallBack = { NULL,NULL,FlashProgressEx };
+
+CALLBACK_INFO SetupCallBack[] =
+{
+ // Last field in every structure will be filled by the Setup
+ { &guidRecovery, &CallBack, RECOVERY_FORM_SET_CLASS, 0, 0},
+};
+
+
+//-------------------------------
+//Before flash and After flash eLinks
+
+typedef VOID (OEM_FLASH_UPDATE_CALLBACK) (VOID);
+extern OEM_FLASH_UPDATE_CALLBACK OEM_BEFORE_FLASH_UPDATE_CALLBACK_LIST EndOfList;
+extern OEM_FLASH_UPDATE_CALLBACK OEM_AFTER_FLASH_UPDATE_CALLBACK_LIST EndOfList;
+OEM_FLASH_UPDATE_CALLBACK* OemBeforeFlashCallbackList[] = { OEM_BEFORE_FLASH_UPDATE_CALLBACK_LIST NULL };
+OEM_FLASH_UPDATE_CALLBACK* OemAfterFlashCallbackList[] = { OEM_AFTER_FLASH_UPDATE_CALLBACK_LIST NULL };
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OemBeforeFlashCallback
+//
+// Description: This function executes OEM porting hooks before starting flash update
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemBeforeFlashCallback(
+ VOID
+)
+{
+ UINT32 i;
+ for(i = 0; OemBeforeFlashCallbackList[i] != NULL; i++)
+ OemBeforeFlashCallbackList[i]();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OemAfterFlashCallback
+//
+// Description: This function executes OEM porting hooks after finishing flash update
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemAfterFlashCallback(
+ VOID
+)
+{
+ UINT32 i;
+ for(i = 0; OemAfterFlashCallbackList[i] != NULL; i++)
+ OemAfterFlashCallbackList[i]();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetHiiString
+//
+// Description: This function reads a string from HII
+//
+// Input: IN EFI_HII_HANDLE HiiHandle - Efi Hii Handle
+// IN STRING_REF Token - String Token
+// IN OUT UINTN *pDataSize - Length of the StringBuffer
+// OUT EFI_STRING *ppData - The buffer to receive the characters in the string.
+//
+// Output: EFI_STATUS - Depending on result
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetHiiString(
+ IN EFI_HII_HANDLE HiiHandle,
+ IN STRING_REF Token,
+ IN OUT UINTN *pDataSize,
+ OUT EFI_STRING *ppData
+)
+{
+ EFI_STATUS Status;
+
+ if (!*ppData) *pDataSize=0;
+
+ Status = HiiLibGetString(HiiHandle, Token, pDataSize, *ppData);
+ if (!EFI_ERROR(Status)) return Status;
+ //--- If size was too small free pool and try with right size, which was passed
+ if (Status==EFI_BUFFER_TOO_SMALL)
+ {
+ if (*ppData) pBS->FreePool(*ppData);
+
+ if (!(*ppData=Malloc(*pDataSize))) return EFI_OUT_OF_RESOURCES;
+
+ Status = HiiLibGetString(HiiHandle, Token, pDataSize, *ppData);
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ApplyUserSelection
+//
+// Description: This function updates flash parameteres based on user selection
+// or Setup values
+//
+// Input:
+// IN BOOLEAN Interactive - if TRUE get selection from user input, otherwise
+// use Setup values
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ApplyUserSelection(
+ IN BOOLEAN Interactive
+)
+{
+ EFI_STATUS Status;
+ AUTOFLASH FlashUpdateControl;
+ UINTN Size = sizeof(FlashUpdateControl);
+ UINT32 i;
+
+ if(Interactive) {
+ /* get values from Setup Browser */
+ Status = HiiLibGetBrowserData(&Size, &FlashUpdateControl, &guidRecovery, L"Setup");
+ } else {
+ /* get values from NVRAM */
+ Status = pRS->GetVariable(L"Setup", &guidRecovery, NULL, &Size, &FlashUpdateControl);
+ }
+ if(EFI_ERROR(Status)) {
+ /* no user selection, use defaults */
+ FlashUpdateControl.UpdateMain = REFLASH_UPDATE_MAIN_BLOCK;
+ FlashUpdateControl.UpdateBb = REFLASH_UPDATE_BOOT_BLOCK;
+ FlashUpdateControl.UpdateNv = REFLASH_UPDATE_NVRAM;
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ FlashUpdateControl.UpdateEC = REFLASH_UPDATE_EC_FIRMWARE;
+#endif
+ }
+
+ for(i = 0; BlocksToUpdate[i].Type != FvTypeMax; i++) {
+ switch(BlocksToUpdate[i].Type) {
+ case FvTypeMain:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateMain;
+#if FtRecovery_SUPPORT
+ if(FlashUpdateControl.UpdateBb == 1)
+ BlocksToUpdate[i].Update = TRUE; //with fault tolerant recovery FV_MAIN is used for backup - force update
+#endif
+ break;
+ case FvTypeBootBlock:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateBb;
+#if FtRecovery_SUPPORT
+ if(IsTopSwapOn()) //if we're here BB update failed we use backup copy - force BB update again
+ BlocksToUpdate[i].Update = TRUE;
+#endif
+ break;
+ case FvTypeNvRam:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateNv;
+ break;
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ case FvTypeCustom:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateEC;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// IsRecovery prototypes
+//----------------------------------------------------------------------------
+// Bit Mask of checks to perform on Aptio FW Image
+// 1- Capsule integrity
+// 2- Verify Signature
+// 3- Verify FW Key
+// 4- Verify FW Version compatibility.
+// To prevent possible re-play attack:
+// update current FW with older version with lower security.
+// 5- Compare MonotonicCounters/date. Replay attack
+//----------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateSetupStrings
+//
+// Description: This function updates status strings in setup window, based
+// on execution results
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - handle of Reflash setup formset (page)
+// IN EFI_STATUS Error - execution error if any
+// IN UINT32 FailedStage - in case of authentication error failed stage description
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateSetupStrings(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_STATUS Error,
+ IN UINT32 FailedStage
+)
+{
+ UINTN Size;
+ EFI_STRING Template = NULL;
+ EFI_STRING Template2 = NULL;
+ CHAR16 ReportString[100];
+
+ if(!EFI_ERROR(Error)) {
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE1_SUCCESS), &Size, &Template);
+ if(FailedStage == 0)
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_SUCCESS), &Size, &Template2);
+ else //if we're here we're on manual BIOS rollback to older version
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_ROLLBACK_WARNING), &Size, &Template2);
+
+ if(Template != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE1), Template);
+ pBS->FreePool(Template);
+ }
+
+ if(Template2 != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE2), Template2);
+ pBS->FreePool(Template2);
+ }
+
+ return;
+ }
+
+//Get Error string template
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE1_ERROR), &Size, &Template);
+ if(Template != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE1), Template);
+ pBS->FreePool(Template);
+ Template = NULL;
+ }
+
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_ERROR_TEMPLATE), &Size, &Template);
+ switch(FailedStage) {
+ case InvalidHeader:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR), &Size, &Template2);
+ break;
+ case InvalidSignature:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR1), &Size, &Template2);
+ break;
+ case IvalidPlatformKey:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR2), &Size, &Template2);
+ break;
+ case InvalidFwVersion:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR3), &Size, &Template2);
+ break;
+ default:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR4), &Size, &Template2);
+ break;
+ }
+
+ if((Template != NULL) && (Template2 != NULL)) {
+ Swprintf(ReportString, Template, Error, Template2);
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE2), ReportString);
+ pBS->FreePool(Template);
+ pBS->FreePool(Template2);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReFlashEntry
+//
+// Description: This is the standard EFI driver entry point called for
+// Recovery flash module initlaization
+// Input: IN EFI_HANDLE ImageHandle - ImageHandle of the loaded driver
+// IN EFI_SYSTEM_TABLE SystemTable - Pointer to the System Table
+//
+// Output: EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EFIAPI ReFlashEntry (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ static EFI_GUID guidHob = HOB_LIST_GUID;
+ static EFI_GUID guidBootFlow = BOOT_FLOW_VARIABLE_GUID;
+ static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+ UINT32 BootFlow = BOOT_FLOW_CONDITION_RECOVERY;
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ UINTN Size;
+ UINT32 Attributes;
+ UINT32 FailedStage;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ AUTOFLASH AutoFlash = {
+ (UINT8)(EFI_SUCCESS),
+ REFLASH_UPDATE_NVRAM,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ REFLASH_UPDATE_MAIN_BLOCK
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ ,REFLASH_UPDATE_EC_FIRMWARE
+#endif
+ };
+
+ ThisImageHandle = ImageHandle;
+ InitAmiLib(ImageHandle,SystemTable);
+
+ //Get Boot Mode
+ pHit = GetEfiConfigurationTable(pST, &guidHob);
+
+ //unload the module if we are not in recovery mode
+ // TODO:need to distinguish between recovery and Flash Update
+ if (!pHit || (pHit->BootMode != BOOT_IN_RECOVERY_MODE && pHit->BootMode != BOOT_ON_FLASH_UPDATE)) {
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+ InstallEsrtTable();
+#endif
+ return EFI_UNLOAD_IMAGE;
+ }
+
+ VERIFY_EFI_ERROR(pBS->LocateProtocol(&gFlashProtocolGuid, NULL, &Flash));
+//Get Recovery Image verification status
+ if(!EFI_ERROR(FindNextHobByGuid(&RecoveryHobGuid, &pHit))) {
+ if(((EFI_HOB_GENERIC_HEADER *)pHit)->HobLength < sizeof(RECOVERY_IMAGE_HOB)) {
+ //we got update from older Core here
+ FailedStage = 0;
+ RecoveryStatus = EFI_SUCCESS;
+ } else {
+ FailedStage = ((RECOVERY_IMAGE_HOB*)pHit)->FailedStage;
+ RecoveryStatus = ((RECOVERY_IMAGE_HOB*)pHit)->Status;
+
+ //Since RECOVERY_IMAGE_HOB Status field is byte long, we should set error bit by ourselves
+ if(RecoveryStatus != NULL)
+ RecoveryStatus |= EFI_ERROR_BIT;
+ }
+ RecoveryBuffer = (UINT8 *)(UINTN)((RECOVERY_IMAGE_HOB*)pHit)->Address;
+ } else { //Recovery Hob not found - should not happen, we always create this hob to report errors
+ FailedStage = 0;
+ RecoveryStatus = EFI_ABORTED;
+ }
+
+ AutoFlash.FailedRecovery = (UINT8)RecoveryStatus;
+
+//Update Reflash parameters
+ Size = sizeof(AUTOFLASH);
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+ pRS->SetVariable(L"Setup", &guidRecovery, Attributes, Size, &AutoFlash);
+
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+//Verify if we're on OS firmware update path
+ Status = IsWin8Update((EFI_ERROR(RecoveryStatus)) ? TRUE : FALSE);
+ if(Status == EFI_SUCCESS || Status == EFI_UNLOAD_IMAGE)
+ return Status;
+#endif
+
+//Load setup page and create error message if necessary
+ LoadResources(ImageHandle, sizeof(SetupCallBack) / sizeof(CALLBACK_INFO), SetupCallBack, NULL);
+ ReflashHiiHandle = SetupCallBack[0].HiiHandle;
+ pRS->SetVariable(L"BootFlow", &guidBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow);
+
+ UpdateSetupStrings(ReflashHiiHandle, RecoveryStatus, FailedStage);
+
+ return EFI_SUCCESS;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.cif b/Core/EM/Recovery/ReFlash/ReFlash.cif
new file mode 100644
index 0000000..8d76667
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "ReFlash"
+ category = ModulePart
+ LocalRoot = "Core\EM\Recovery\ReFlash\"
+ RefName = "ReFlash"
+[files]
+"ReFlash.sdl"
+"ReFlash.mak"
+"ReFlash.vfr"
+"ReFlash.c"
+"ReFlashWorker.c"
+"ReFlash.dxs"
+"ReFlash.uni"
+"ReFlash.h"
+"Esrt.c"
+<endComponent>
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.dxs b/Core/EM/Recovery/ReFlash/ReFlash.dxs
new file mode 100644
index 0000000..11e6c8d
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.dxs
@@ -0,0 +1,72 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/ReFlash.dxs 3 10/09/09 6:30p Felixp $
+//
+// $Revision: 3 $
+//
+// $Date: 10/09/09 6:30p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/ReFlash.dxs $
+//
+// 3 10/09/09 6:30p Felixp
+// ReFlash component is updated to support Framework and UEFI 2.1 HII
+//
+// 2 5/21/09 4:44p Felixp
+// ReFlash driver is updated to use FlashProtocol instead of Flash library
+// functions.
+//
+// 1 12/01/05 9:35a Felixp
+//
+// 1 11/08/05 4:04a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlash.dxs
+//
+// Description: Dependancy expression for the component
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#if EFI_SPECIFICATION_VERSION>0x20000
+#include <Protocol/HiiDatabase.h>
+#else
+#include <Protocol/HII.h>
+#endif
+#include <Protocol/FlashProtocol.h>
+DEPENDENCY_START
+#if EFI_SPECIFICATION_VERSION>0x20000
+ EFI_HII_DATABASE_PROTOCOL_GUID
+#else
+ EFI_HII_PROTOCOL_GUID
+#endif
+ AND FLASH_PROTOCOL_GUID
+DEPENDENCY_END
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.h b/Core/EM/Recovery/ReFlash/ReFlash.h
new file mode 100644
index 0000000..26ad479
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.h
@@ -0,0 +1,268 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlash.h 2 4/16/13 5:50a Thomaschen $
+//
+// $Revision: 2 $
+//
+// $Date: 4/16/13 5:50a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlash.h $
+//
+// 2 4/16/13 5:50a Thomaschen
+// Fixed for EIP106722.
+//
+// 13 1/02/13 12:18p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Flash update progress report changes:
+// - report progress in non-interactive flash update
+// - do not report progress in Win8-style flash update
+// [Files] ReflashWorker.c Reflash.h Esrt.c
+//
+// 12 7/20/12 10:20a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+// 11 5/22/12 4:44p Artems
+// [TAG] EIP88314
+// [Description] Recovery takes a long time for large flash size
+// Rewrite reflash code to not give control back to TSE until finished
+// reporting progress via DisplayProgress API of AMI Post manager
+// [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+// Reflash.uni
+//
+// 10 11/12/11 6:49p Artems
+// Added fault tolerant recovery support
+//
+// 9 5/13/11 4:52p Artems
+// Added extended error reporting for secure flash update/recovery
+//
+// 8 11/17/10 2:52p Felixp
+// Enhencement (EIP 36355):
+// The Reflash component is updated to be extensible with external
+// eModules.
+// The eModules can contribute content for the Recovery setup page,
+// and provide callback function that will be periodically called
+// once BIOS update is completed.The external eModules can be used
+// to implement update of non-standard firmware components.
+// For example, update of the non-shared EC firmware.
+//
+// 7 12/24/09 12:42p Oleksiyy
+// EIP 30173: Support for the EC Firmware Area Update control added. Main
+// token to enable this support is EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+// should be located in specific EC-related .sdl file.
+//
+// 6 10/09/09 6:30p Felixp
+// ReFlash component is updated to support Framework and UEFI 2.1 HII
+//
+// 5 7/09/09 5:59p Oleksiyy
+// Files clean-up, some headers added
+//
+// 4 10/19/07 6:23p Felixp
+// Recovery Flash Update module extended to support Boot Block update.
+// Boot block update can be enabled or disabled using SDL token.
+// In addition to that there is an SDL token that enables/disables
+// checkbox on the
+// recovery setup page that user can use to enable or disable boot block
+// update.
+//
+// 3 4/13/07 6:08p Ambikas
+// Coding standard changes: updated the year in the AMI copyright
+// header/footer.
+//
+// 2 12/22/06 9:38a Felixp
+// Support for optional NVRAM reset based on user input added
+//
+// 1 12/01/05 9:35a Felixp
+//
+// 1 11/08/05 4:04a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlash.h
+//
+// Description: Header file for component
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __REFLASH__H__
+#define __REFLASH__H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <ReFlashStrTokens.h>
+#include <Token.h>
+#ifndef VFRCOMPILE
+#include <AmiDxeLib.h>
+#include <Protocol/FlashProtocol.h>
+#endif
+
+#define RECOVERY_FORM_SET_CLASS 0x40
+// {80E1202E-2697-4264-9CC9-80762C3E5863}
+#define RECOVERY_FORM_SET_GUID { 0x80e1202e, 0x2697, 0x4264, 0x9c, 0xc9, 0x80, 0x76, 0x2c, 0x3e, 0x58, 0x63 }
+
+#if REFLASH_INTERACTIVE
+#define RECOVERY_MAIN 1
+#define RECOVERY_FLASH 2
+#else
+#define RECOVERY_FLASH 1
+#endif
+
+#define FLASH_PROGRESS_KEY 100
+#define FLASH_START_KEY 101
+
+#pragma pack(push, 1)
+typedef struct {
+ UINT8 FailedRecovery; // EFI_STATUS error code
+ UINT8 UpdateNv;
+ UINT8 UpdateBb;
+ UINT8 UpdateMain;
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ UINT8 UpdateEC;
+#endif
+
+#define REFLASH_DATA_DEFINITION
+#include <ReflashDefinitions.h>
+#undef REFLASH_DATA_DEFINITION
+
+} AUTOFLASH;
+#pragma pack(pop)
+
+#include <Setup.h>
+
+#ifndef VFRCOMPILE
+
+#define FW_VERSION_VARIABLE L"AmiFwVersion"
+
+typedef enum {
+ FvTypeMain,
+ FvTypeBootBlock,
+ FvTypeNvRam,
+ FvTypeCustom,
+ FvTypeMax
+} FLASH_FV_TYPE;
+
+typedef struct _FLASH_AREA_EX FLASH_AREA_EX;
+
+typedef EFI_STATUS (REFLASH_FUNCTION_EX)(
+ IN FLASH_AREA_EX *Block,
+ IN UINTN BlockNumber
+);
+
+struct _FLASH_AREA_EX
+{
+ UINT8 *BlockAddress;
+ UINT8 *BackUpAddress;
+ UINTN Size;
+ UINT32 BlockSize;
+ FLASH_FV_TYPE Type;
+ BOOLEAN Update;
+ BOOLEAN TopSwapTrigger;
+ REFLASH_FUNCTION_EX *BackUp;
+ REFLASH_FUNCTION_EX *Program;
+ EFI_STRING_ID BackUpString;
+ EFI_STRING_ID ProgramString;
+};
+
+extern FLASH_AREA_EX BlocksToUpdate[];
+extern FLASH_PROTOCOL *Flash;
+extern EFI_HII_HANDLE ReflashHiiHandle;
+extern UINT8 *RecoveryBuffer;
+
+EFI_STATUS GetHiiString(
+ IN EFI_HII_HANDLE HiiHandle,
+ IN STRING_REF Token,
+ IN OUT UINTN *pDataSize,
+ OUT EFI_STRING *ppData
+);
+
+EFI_STATUS AmiFlashBackUp(
+ IN FLASH_AREA_EX *Block,
+ IN UINTN BlockNumber
+);
+EFI_STATUS AmiFlashProgram(
+ IN FLASH_AREA_EX *Block,
+ IN UINTN BlockNumber
+);
+
+VOID ApplyUserSelection(
+ IN BOOLEAN Interactive
+);
+
+VOID OemBeforeFlashCallback(
+ VOID
+);
+
+VOID OemAfterFlashCallback(
+ VOID
+);
+
+EFI_STATUS FlashProgressEx(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID KeyValue,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+);
+
+EFI_STATUS IsWin8Update(
+ BOOLEAN RecoveryFailed
+);
+
+EFI_STATUS FlashWalker(
+ IN BOOLEAN BackUp
+);
+
+EFI_STATUS Epilogue(
+ VOID
+);
+
+EFI_STATUS Prologue(
+ IN BOOLEAN Interactive,
+ IN BOOLEAN Win8StyleUpdate
+);
+
+EFI_STATUS InstallEsrtTable(
+ VOID
+);
+
+#endif
+ /****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.mak b/Core/EM/Recovery/ReFlash/ReFlash.mak
new file mode 100644
index 0000000..6edcd3e
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.mak
@@ -0,0 +1,135 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/BIN/Core/Modules/Recovery/ReFlash.mak 15 5/22/12 5:10p Artems $
+#
+# $Revision: 15 $
+#
+# $Date: 5/22/12 5:10p $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/BIN/Core/Modules/Recovery/ReFlash.mak $
+#
+# 15 5/22/12 5:10p Artems
+# [TAG] EIP88314
+# [Category] Improvement
+# [Description] Recovery takes a long time for large flash size
+# Rewrite reflash code to not give control back to TSE until finished
+# reporting progress via DisplayProgress API of AMI Post manager
+# [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+# Reflash.uni
+#
+# 14 12/05/11 1:48p Artems
+# EIP 74623: Add capabilities similar to ones in SMIFlash module
+#
+# 13 11/29/11 3:33p Artems
+# Fixed build error when FtRecovery module is present but disabled
+#
+# 12 11/12/11 6:47p Artems
+# Added fault tolerant recovery support
+#
+# 11 11/30/10 5:04p Felixp
+# Bug fix: VfrCompile build error when ReflashFunctions eLink list
+# contains more than one function.
+#
+# 10 11/17/10 5:27p Felixp
+# $(BUILD_DIR)\ReFlash.mak dependency is updated.
+#
+# 9 11/17/10 2:52p Felixp
+# Enhencement (EIP 36355):
+# The Reflash component is updated to be extensible with external
+# eModules.
+# The eModules can contribute content for the Recovery setup page,
+# and provide callback function that will be periodically called
+# once BIOS update is completed.The external eModules can be used
+# to implement update of non-standard firmware components.
+# For example, update of the non-shared EC firmware.
+#
+# 8 10/01/10 2:14p Felixp
+# Previous changes related to descrete EC firmware update are rolled back
+# for the Core labeling.
+#
+# 6 2/23/10 9:20p Felixp
+# Support of the ReFlash String Override via REFLASH_SDBS eLink (EIP
+# 32696).
+#
+# 5 7/09/09 5:59p Oleksiyy
+# Files clean-up, some headers added
+#
+# 4 12/29/06 2:58p Felixp
+# RecoveryDxeLib removed. Functionality moved to Flash.lib
+#
+# 3 8/24/06 9:19a Felixp
+# x64 Support
+#
+# 1 11/08/05 4:04a Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: ReFlash.mak
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : ReFlash
+
+SetupData : ReFlash
+
+ReFlash : $(BUILD_DIR)\ReFlash.mak ReFlashBin
+
+$(BUILD_DIR)\ReFlash.mak : $(ReFlash_DIR)\$(@B).cif $(ReFlash_DIR)\$(@B).mak $(BUILD_RULES) $(REFLASH_CIFS) $(BUILD_DIR)\token.h
+ $(CIF2MAK) $(ReFlash_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(REFLASH_CIFS)
+
+REFLASH_LISTS = \
+/D\"REFLASH_FUNCTION_LIST=$(ReflashFunctions)\"\
+/D\"OEM_BEFORE_FLASH_UPDATE_CALLBACK_LIST=$(OemBeforeFlashUpdateList)\"\
+/D\"OEM_AFTER_FLASH_UPDATE_CALLBACK_LIST=$(OemAfterFlashUpdateList)\"
+
+ReFlashBin : $(AMIDXELIB) $(FLASHLIB)
+ type << >$(BUILD_DIR)\ReflashDefinitions.h
+!IF "$(REFLASH_DEFINITIONS)"!=""
+#include<$(REFLASH_DEFINITIONS: =>^
+#include<)>
+!ENDIF
+<<
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\ReFlash.mak all\
+ GUID=70e1a818-0be1-4449-bfd4-9ef68c7f02a8\
+ ENTRY_POINT=ReFlashEntry\
+ "EXT_HEADERS=$(BUILD_DIR)\token.h"\
+ TYPE=BS_DRIVER \
+ MY_INCLUDES=/I$(ReFlash_DIR)\
+ "CFLAGS=$(CFLAGS) $(REFLASH_LISTS)"\
+ COMPRESS=1 HAS_RESOURCES=1\
+!IF "$(REFLASH_SDBS: =)"!=""
+ "MY_SDBS=-db $(REFLASH_SDBS: = -db )"\
+!ENDIF
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.sdl b/Core/EM/Recovery/ReFlash/ReFlash.sdl
new file mode 100644
index 0000000..db29792
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.sdl
@@ -0,0 +1,135 @@
+TOKEN
+ Name = "ReFlash_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable ReFlash support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "REFLASH_INTERACTIVE"
+ Value = "1"
+ Help = "When this switch is enabled, flash update process is interactive.\User can adjust update parameters before the update.\User can also choose not to update the flash.\Once update is completed user has to press a key to reset the system\When this switch is disabled, flash update process is started automatically.\User can only monitor progress of the operation.\Once update is completed system resets."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_NVRAM_CONTROL"
+ Value = "1"
+ Help = "Eanbles/Disables Setup option that that controls NVRAM update"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "REFLASH_INTERACTIVE" "=" "1"
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_NVRAM"
+ Value = "1"
+ Help = "Enables/Disables update of the NVRAM flash area.\When REFLASH_INTERACTIVE is on and REFLASH_UPDATE_NVRAM_CONTROL is on\this value can be overriden by the user using setup option."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_BOOT_BLOCK_CONTROL"
+ Value = "0"
+ Help = "Enables/Disables Setup option that controls boot block update"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "REFLASH_INTERACTIVE" "=" "1"
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_BOOT_BLOCK"
+ Value = "0"
+ Help = "Enables/Disables update of the boot block flash area.\When REFLASH_INTERACTIVE is on and REFLASH_UPDATE_BOOT_BLOCK_CONTROL is on\this value can be overriden by the user using setup option."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_MAIN_BLOCK"
+ Value = "1"
+ Help = "Enables/Disables update of the Main block flash area.\When REFLASH_INTERACTIVE is on and REFLASH_UPDATE_BOOT_BLOCK_CONTROL is on\this value can be overriden by the user using setup option."
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_EC_FIRMWARE_CONTROL"
+ Value = "0"
+ Help = "Eanbles/Disables Setup option that controls EC FIRMWARE update"
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "REFLASH_INTERACTIVE" "=" "1"
+ Token = "EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT" "=" "1"
+End
+
+TOKEN
+ Name = "REFLASH_UPDATE_EC_FIRMWARE"
+ Value = "0"
+ Help = "Enables/Disables update of the EC FIRMWARE flash area.\When REFLASH_INTERACTIVE is on and REFLASH_UPDATE_EC_FIRMWARE_CONTROL is on\this value can be overriden by the user using setup option."
+ TokenType = Boolean
+ TargetH = Yes
+ Token = "EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT" "=" "1"
+End
+
+PATH
+ Name = "ReFlash_DIR"
+End
+
+MODULE
+ Help = "Includes ReFlash.mak to Project"
+ File = "ReFlash.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\ReFlash.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\$(ReFlash_DIR)"
+ Parent = "IFR_DIR_LIST"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "REFLASH_SDBS"
+ Help = "List of SDB files with the string overrides for the ReFlash component"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "REFLASH_CIFS"
+ Help = "List of CIF files of the ReFlash plug-ins"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "REFLASH_DEFINITIONS"
+ Help = "List of SD files of the ReFlash plug-ins"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "ReflashFunctions"
+ Help = "List of callback functions of the ReFlash plug-ins"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OemBeforeFlashUpdateList"
+ Help = "List of callback functions to be called before flash update"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "OemAfterFlashUpdateList"
+ Help = "List of callback functions to be called after flash update"
+ InvokeOrder = ReplaceParent
+End
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.uni b/Core/EM/Recovery/ReFlash/ReFlash.uni
new file mode 100644
index 0000000..13e42f7
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.uni
Binary files differ
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.vfr b/Core/EM/Recovery/ReFlash/ReFlash.vfr
new file mode 100644
index 0000000..5884ea2
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.vfr
@@ -0,0 +1,240 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/ReFlash.vfr 17 5/22/12 5:12p Artems $
+//
+// $Revision: 17 $
+//
+// $Date: 5/22/12 5:12p $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/ReFlash.vfr $
+//
+// 17 5/22/12 5:12p Artems
+// [TAG] EIP88314
+// [Category] Improvement
+// [Description] Recovery takes a long time for large flash size
+// Rewrite reflash code to not give control back to TSE until finished
+// reporting progress via DisplayProgress API of AMI Post manager
+//
+// [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+// Reflash.uni
+//
+// 16 11/12/11 6:48p Artems
+// Added fault tolerant recovery support
+//
+// 15 11/02/11 4:53p Artems
+// EIP 74446: Fixed bug - reflash is enabled when recovery image is not
+// found
+//
+// 14 5/13/11 4:49p Artems
+// Added REFLASH_UPDATE_MAIN_BLOCK setup control
+//
+// 13 11/17/10 2:52p Felixp
+// Enhencement (EIP 36355):
+// The Reflash component is updated to be extensible with external
+// eModules.
+// The eModules can contribute content for the Recovery setup page,
+// and provide callback function that will be periodically called
+// once BIOS update is completed.The external eModules can be used
+// to implement update of non-standard firmware components.
+// For example, update of the non-shared EC firmware.
+//
+// 12 10/01/10 2:14p Felixp
+// Previous changes related to descrete EC firmware update are rolled back
+// for the Core labeling.
+//
+// 10 12/24/09 12:41p Oleksiyy
+// EIP 30173: Support for the EC Firmware Area Update control added. Main
+// token to enable this support is EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+// should be located in specific EC-related .sdl file.
+//
+// 9 12/14/09 3:11p Aaronp
+// Updated to support UEFI2.1 interactive text
+//
+// 8 10/09/09 6:30p Felixp
+// ReFlash component is updated to support Framework and UEFI 2.1 HII
+//
+// 7 7/09/09 5:59p Oleksiyy
+// Files clean-up, some headers added
+//
+// 6 10/22/08 9:36a Felixp
+// Bug fix (EIP 15931): NVRAM was never reset during BIOS Recovery. Even
+// when 'Reset NVRAM' setup option was enabled.
+// The bug was caused by the wrong varstore passed into the callback
+// routine.
+// Form layout has been changed to make sure default varstore is active
+// when goto statement is reached.
+//
+// 5 10/09/08 5:30p Felixp
+// Bug fix (EIP 13077): During BIOS Recovery the warning about flash
+// update being disabled due to the user access level was truncated
+//
+// 4 1/17/08 5:30p Felixp
+// Updated to disable flash update option during boot with the USER access
+// level
+//
+// 3 10/19/07 6:23p Felixp
+// Recovery Flash Update module extended to support Boot Block update.
+// Boot block update can be enabled or disabled using SDL token.
+// In addition to that there is an SDL token that enables/disables
+// checkbox on the
+// recovery setup page that user can use to enable or disable boot block
+// update.
+//
+// 2 12/22/06 9:38a Felixp
+// Support for optional NVRAM reset based on user input added
+//
+// 1 12/01/05 9:35a Felixp
+//
+// 1 11/08/05 4:04a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlash.vfr
+//
+// Description: Reflash formset
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include "ReFlash.h"
+
+formset guid = RECOVERY_FORM_SET_GUID,
+ title = STRING_TOKEN(STR_RECOVERY),
+ help = STRING_TOKEN(STR_EMPTY),
+ class = RECOVERY_FORM_SET_CLASS, subclass = 0,
+
+ varstore AUTOFLASH,
+ name = Setup,
+ guid = RECOVERY_FORM_SET_GUID;
+
+ AMI_CALLBACK_VARSTORE
+ SYSTEM_ACCESS_VARSTORE
+
+
+#if REFLASH_INTERACTIVE
+
+ form formid = RECOVERY_MAIN,
+ title = STRING_TOKEN(STR_RECOVERY);
+
+ SUBTITLE(STRING_TOKEN(STR_SUBTITLE1))
+ SUBTITLE(STRING_TOKEN(STR_SUBTITLE2))
+
+ suppressif ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_ADMIN;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_ACCESS_DENIED),
+ text = STRING_TOKEN(STR_ACCESS_DENIED2),
+ flags = 0, key = 0;
+ text
+ help = STRING_TOKEN(STR_EMPTY),
+ text = STRING_TOKEN(STR_ACCESS_DENIED3),
+ text = STRING_TOKEN(STR_ACCESS_DENIED4),
+ flags = 0, key = 0;
+ endif;
+
+ SEPARATOR
+
+ SUBTITLE(STRING_TOKEN(STR_OPTIONS))
+
+ grayoutif NOT ideqval AUTOFLASH.FailedRecovery == 0 OR ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+
+#if REFLASH_UPDATE_NVRAM_CONTROL
+ checkbox varid = AUTOFLASH.UpdateNv,
+ prompt = STRING_TOKEN(STR_UPDATE_NVRAM),
+ help = STRING_TOKEN(STR_UPDATE_NVRAM_HELP),
+ flags = REFLASH_UPDATE_NVRAM, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off
+ endcheckbox;
+#endif
+#if REFLASH_UPDATE_BOOT_BLOCK_CONTROL
+ checkbox varid = AUTOFLASH.UpdateBb,
+ prompt = STRING_TOKEN(STR_UPDATE_BB),
+ help = STRING_TOKEN(STR_UPDATE_BB_HELP),
+ flags = REFLASH_UPDATE_BOOT_BLOCK, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off
+ endcheckbox;
+#endif
+
+ checkbox varid = AUTOFLASH.UpdateMain,
+ prompt = STRING_TOKEN(STR_UPDATE_MAIN),
+ help = STRING_TOKEN(STR_UPDATE_MAIN_HELP),
+ flags = REFLASH_UPDATE_MAIN_BLOCK, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off
+#if FtRecovery_SUPPORT
+ inconsistentif prompt = STRING_TOKEN(STR_FLASH_SELECTION_ERROR_POPUP),
+ ideqval AUTOFLASH.UpdateBb == 1
+ AND
+ ideqval AUTOFLASH.UpdateMain == 0
+ endif
+#endif
+ endcheckbox;
+#if REFLASH_UPDATE_EC_FIRMWARE_CONTROL
+ checkbox varid = AUTOFLASH.UpdateEC,
+ prompt = STRING_TOKEN(STR_UPDATE_EC),
+ help = STRING_TOKEN(STR_UPDATE_EC_HELP),
+ flags = REFLASH_UPDATE_EC_FIRMWARE, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off
+ endcheckbox;
+#endif
+
+#define REFLASH_CONTROL
+#include <ReflashDefinitions.h>
+#undef REFLASH_CONTROL
+
+ //Can't use 'SEPARATOR' because it's not allowed in the grayoutif scope
+ INVENTORY(STRING_TOKEN(STR_EMPTY),STRING_TOKEN(STR_EMPTY))
+
+ endif;//grayoutif
+
+ suppressif NOT ideqval AUTOFLASH.FailedRecovery == 0 OR ideqval SYSTEM_ACCESS.Access == SYSTEM_PASSWORD_USER;
+ goto RECOVERY_FLASH,
+ prompt = STRING_TOKEN(STR_FLASH),
+ help = STRING_TOKEN(STR_FLASH_HELP),
+ flags = INTERACTIVE, key = FLASH_START_KEY;
+ endif;
+ endform;
+#endif //#if REFLASH_INTERACTIVE
+
+ form formid = RECOVERY_FLASH,
+ title = STRING_TOKEN(STR_RECOVERY_FLASH);
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING1))
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING2))
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING3))
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING_RESET))
+#if REFLASH_INTERACTIVE
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING_RESET_USER))
+#else
+ SUBTITLE(STRING_TOKEN(STR_UPDATE_WARNING_RESET_AUTO))
+#endif
+ SEPARATOR
+
+ INTERACTIVE_TEXT(STRING_TOKEN(STR_FLASH_PROGRESS_HELP), STRING_TOKEN(STR_EMPTY), STRING_TOKEN(STR_EMPTY), FLASH_PROGRESS_KEY)
+#define REFLASH_PROGRESS
+#include <ReflashDefinitions.h>
+#undef REFLASH_PROGRESS
+ endform;
+endformset;
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/ReFlash/ReFlashWorker.c b/Core/EM/Recovery/ReFlash/ReFlashWorker.c
new file mode 100644
index 0000000..6ab6fa7
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlashWorker.c
@@ -0,0 +1,720 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlashWorker.c 3 5/13/13 6:26a Thomaschen $
+//
+// $Revision: 3 $
+//
+// $Date: 5/13/13 6:26a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlashWorker.c $
+//
+// 3 5/13/13 6:26a Thomaschen
+// Update for EIP122037.
+//
+// 2 4/16/13 5:47a Thomaschen
+// Fixed for EIP106722.
+//
+//
+// 7 2/11/13 3:42p Artems
+// [TAG] EIP112180
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] In non-interactive mode system updated flash even when
+// there is no valid image
+// [RootCause] In non-interactive mode system didn't check flash image
+// validity
+// [Solution] Added check of flash image validity. Inform user if image
+// is invalid or not found
+// [Files] Reflash.c ReflashWorker.c Reflash.uni Reflash.vfr
+//
+// 6 1/02/13 12:20p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Flash update progress report changes:
+// - report progress in non-interactive flash update
+// - do not report progress in Win8-style flash update
+// [Files] ReflashWorker.c Reflash.h Esrt.c
+//
+// 5 8/02/12 12:00p Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c
+//
+// 4 7/24/12 11:56a Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Added dependency on fault-tolerant support module in
+// top-swap triggering code
+// [Files] ReflashWorker.c
+//
+// 3 7/20/12 10:19a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+// 2 6/08/12 12:35p Artems
+// [TAG] EIP88314
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Incorrect strings in progress message
+// [RootCause] String tokens were twisted up
+// [Solution] Put string tokens in a correct order
+// [Files] ReflashWorker.c
+//
+// 1 5/23/12 1:19p Artems
+// [TAG] EIP 88314
+// [Category] Improvement
+// [Description] Recovery takes a long time for large flash size
+// Rewrite reflash code to not give control back to TSE until finished
+// reporting progress via DisplayProgress API of AMI Post manager
+//
+// [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+// Reflash.uni
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlashWorker.c
+//
+// Description: Implementation of Reflash driver
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+#include <FFS.h>
+#include <AmiCspLib.h>
+#include <Protocol/AmiPostMgr.h>
+#include <Protocol/ConsoleControl.h>
+#include "Reflash.h"
+
+#define FLASH_PART_START_ADDRESS (0xFFFFFFFF - FLASH_SIZE + 1)
+static UINT32 FlashEraser = (FLASH_ERASE_POLARITY) ? 0 : 0xffffffff;
+static UINT8 *FlashPartStart = (UINT8 *)(UINTN)FLASH_PART_START_ADDRESS;
+extern EFI_STATUS RecoveryStatus;
+
+FLASH_AREA_EX BlocksToUpdate[] = {
+#if FtRecovery_SUPPORT
+ {
+ (UINT8 *)FV_RECOVERY_BASE,
+ (UINT8 *)FV_RECOVERY_BACKUP_ADDRESS,
+ FV_RECOVERY_BLOCKS * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeBootBlock,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ FALSE,
+ AmiFlashBackUp,
+ AmiFlashProgram,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_BACKUP_RECOVERY),
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_RECOVERY)
+ },
+ {
+ (UINT8 *)FV_BB_BASE,
+ (UINT8 *)FV_BB_BACKUP_ADDRESS,
+ (FV_BB_BLOCKS - FV_RECOVERY_BLOCKS) * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeBootBlock,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ TRUE,
+ AmiFlashBackUp,
+ AmiFlashProgram,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_BACKUP_BB),
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_BB)
+ },
+#else
+ {
+ (UINT8 *)FV_BB_BASE,
+ NULL,
+ FV_BB_BLOCKS * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeBootBlock,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ FALSE,
+ NULL,
+ AmiFlashProgram,
+ 0,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_BB)
+ },
+#endif
+
+// EIP122037>>
+#if INTEL_FIT_SUPPORT
+ {
+ (UINT8 *)FV_DATA_BASE,
+ NULL,
+ FV_DATA_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeBootBlock,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ FALSE,
+ NULL,
+ AmiFlashProgram,
+ 0,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_DATA)
+ },
+#endif
+// EIP122037<<
+ {
+ (UINT8 *)FV_MAIN_BASE,
+ NULL,
+ FV_MAIN_BLOCKS * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeMain,
+ REFLASH_UPDATE_MAIN_BLOCK,
+ FALSE,
+ NULL,
+ AmiFlashProgram,
+ 0,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_MAIN)
+ },
+ {
+ (UINT8 *)NVRAM_ADDRESS,
+ NULL,
+ NVRAM_BLOCKS * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeNvRam,
+ REFLASH_UPDATE_NVRAM,
+ FALSE,
+ NULL,
+ AmiFlashProgram,
+ 0,
+ STRING_TOKEN(STR_FLASH_PROGRESS_MESSAGE_FLASH_NVRAM)
+ },
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ {
+ (UINT8 *)EC_BASE,
+ NULL,
+ EC_BLOCKS * FLASH_BLOCK_SIZE,
+ FLASH_BLOCK_SIZE,
+ FvTypeCustom,
+ REFLASH_UPDATE_EC_FIRMWARE,
+ FALSE,
+ NULL,
+ AmiFlashProgram,
+ 0,
+ STRING_TOKEN(STR_FLASH_PROGRESS_CAPTION_FLASH)
+ },
+#endif
+
+ {
+ NULL,
+ NULL,
+ 0,
+ 0,
+ FvTypeMax,
+ FALSE,
+ FALSE,
+ NULL,
+ NULL,
+ 0,
+ 0
+ } //terminator
+};
+
+
+
+static EFI_GUID AmiPostManagerProtocolGuid = AMI_POST_MANAGER_PROTOCOL_GUID;
+static AMI_POST_MANAGER_PROTOCOL *AmiPostMgr = NULL;
+static EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
+static BOOLEAN UserConfirmation = TRUE;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: DrawMessageBox
+//
+// Description: This function draws message box on screen and waits till user presses Enter
+//
+// Input:
+// IN CHAR16 *Caption - message box caption
+// IN CHAR16 *Message - message box message
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID DrawMessageBox(
+ IN CHAR16 *Caption,
+ IN CHAR16 *Message
+)
+{
+ EFI_STATUS Status;
+ UINT8 MsgKey;
+
+ if(!UserConfirmation)
+ return;
+
+ if(AmiPostMgr != NULL) {
+ if(ConsoleControl != NULL)
+ ConsoleControl->LockStdIn(ConsoleControl, L"");
+
+ pST->ConIn->Reset(pST->ConIn, FALSE); //discard all keystrokes happend during flash update
+
+ Status = AmiPostMgr->DisplayMsgBox(Caption, Message, MSGBOX_TYPE_OK, &MsgKey);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: CountDown
+//
+// Description: This function draws ResetSystem waiting bar
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+//TODO
+VOID CountDown(
+ VOID
+)
+{
+ pBS->Stall(5000000);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Prologue
+//
+// Description: This function is called before actual flashing takes place
+//
+// Input:
+// IN BOOLEAN Interactive - if TRUE reflash is interactive
+// IN BOOLEAN Win8StyleUpdate - if TRUE reflash is Win8Style
+//
+// Output:
+// EFI_SUCCESS - system prepared for flashing
+// EFI_NOT_STARTED - recovery image not found
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Prologue(
+ IN BOOLEAN Interactive,
+ IN BOOLEAN Win8StyleUpdate
+)
+{
+ static BOOLEAN Executed = FALSE;
+ static EFI_STATUS Status = EFI_SUCCESS;
+
+ if(Executed)
+ return Status;
+
+ Executed = TRUE;
+ ApplyUserSelection(Interactive);
+
+ if(!Win8StyleUpdate) //we do not report progress during Win8-style flash update
+ Status = pBS->LocateProtocol(&AmiPostManagerProtocolGuid, NULL, &AmiPostMgr);
+
+ if(Interactive) {
+ Status = pBS->LocateProtocol(&gEfiConsoleControlProtocolGuid, NULL, &ConsoleControl);
+ if(!EFI_ERROR(Status))
+ ConsoleControl->LockStdIn(ConsoleControl, L"");
+ } else {
+ if(EFI_ERROR(RecoveryStatus)) { //we can't perform flash update, inform user and return error for resetting system
+ CountDown();
+ return EFI_ABORTED;
+ }
+ UserConfirmation = FALSE;
+ }
+
+ OemBeforeFlashCallback();
+ Flash->DeviceWriteEnable();
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: Epilogue
+//
+// Description: This function is called after actual flashing takes place
+//
+// Input:
+// None
+//
+// Output: (this function is not supposed to return control to caller
+// EFI_SUCCESS - flash updated successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS Epilogue(VOID)
+{
+ Flash->DeviceWriteDisable();
+ OemAfterFlashCallback();
+
+ DrawMessageBox(L"Flash update", L"Flash update completed. Press Enter key to reset the system");
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: FlashWalker
+//
+// Description: This function walks through flash regions and calls respective
+// backup and flash functions
+//
+// Input:
+// IN BOOLEAN BackUp - if TRUE, backup functions should be called on this pass
+// flash programm functions should be called otherwise
+//
+// Output:
+// EFI_SUCCESS - flash updated successfully
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FlashWalker(
+ IN BOOLEAN BackUp
+)
+{
+ EFI_STATUS Status;
+ UINTN i;
+ UINTN k;
+ EFI_STRING Title;
+ EFI_STRING Message;
+ UINTN Size;
+ UINTN Step;
+ UINTN Threshold;
+ UINTN Blocks;
+
+ VOID *DisplayHandle;
+ AMI_POST_MGR_KEY OutKey;
+
+ if(AmiPostMgr != NULL) {
+ Title = NULL;
+ if(BackUp)
+ GetHiiString(ReflashHiiHandle, STRING_TOKEN(STR_FLASH_PROGRESS_TITLE_BACKUP), &Size, &Title);
+ else
+ GetHiiString(ReflashHiiHandle, STRING_TOKEN(STR_FLASH_PROGRESS_TITLE_FLASH), &Size, &Title);
+
+ AmiPostMgr->DisplayProgress(AMI_PROGRESS_BOX_INIT,
+ (Title == NULL) ? L"Flash Update Progress" : Title,
+ NULL,
+ NULL,
+ 0,
+ &DisplayHandle,
+ &OutKey);
+ }
+
+ for(i = 0; BlocksToUpdate[i].Type != FvTypeMax; i++) {
+ if(!BlocksToUpdate[i].Update)
+ continue; //block is not updated
+
+ if(BackUp && BlocksToUpdate[i].BackUp == NULL)
+ continue; //no backup function
+
+ if(AmiPostMgr != NULL) {
+ /* prepare display progress window */
+ Message = NULL;
+ if(BackUp)
+ GetHiiString(ReflashHiiHandle, BlocksToUpdate[i].BackUpString, &Size, &Message);
+ else
+ GetHiiString(ReflashHiiHandle, BlocksToUpdate[i].ProgramString, &Size, &Message);
+ }
+
+ /* calculate number of blocks to flash */
+ Blocks = BlocksToUpdate[i].Size / BlocksToUpdate[i].BlockSize;
+
+ /* calculate progress steps */
+ Step = 0;
+ if(Blocks > 100) {
+ Threshold = (Blocks / 100) + 1;
+ } else {
+ Threshold = 1;
+ }
+
+ /* now we're ready to do actual job */
+ for(k = 0; k < Blocks; k++) {
+ if(BackUp)
+ Status = BlocksToUpdate[i].BackUp(&BlocksToUpdate[i], k);
+ else
+ Status = BlocksToUpdate[i].Program(&BlocksToUpdate[i], k);
+
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Step++;
+ if(Step == Threshold && AmiPostMgr != NULL) {
+ /* report progress to user */
+ AmiPostMgr->DisplayProgress(AMI_PROGRESS_BOX_UPDATE,
+ (Title == NULL) ? L"Flash Update Progress" : Title,
+ (Message == NULL) ? L"Flash new data" : Message,
+ NULL,
+ (k * 100) / Blocks,
+ &DisplayHandle,
+ &OutKey);
+ Step = 0;
+ }
+ }
+
+#if FtRecovery_SUPPORT
+ /* check if TopSwap should be triggered */
+ if(BlocksToUpdate[i].TopSwapTrigger) {
+ if(BackUp)
+ SetTopSwap(TRUE);
+ else
+ SetTopSwap(FALSE);
+ }
+#endif
+ }
+
+ if(AmiPostMgr != NULL) {
+ /* close progress window */
+ AmiPostMgr->DisplayProgress(AMI_PROGRESS_BOX_CLOSE,
+ (Title == NULL) ? L"Flash Update Progress" : Title,
+ NULL,
+ NULL,
+ 0,
+ &DisplayHandle,
+ &OutKey);
+ }
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: FlashProgressEx
+//
+// Description: This function is called by Setup browser to perform flash update
+//
+// Input:
+// IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This - pointer to the instance of
+// ConfigAccess protocol
+// IN EFI_BROWSER_ACTION Action - action, that setup browser is performing
+// IN EFI_QUESTION_ID KeyValue - value of currently processed setup control
+// IN UINT8 Type - value type of setup control data
+// IN EFI_IFR_TYPE_VALUE *Value - pointer to setup control data
+// OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - pointer where to store requested action
+//
+// Output:
+// EFI_SUCCESS - flash updated successfully
+// EFI_UNSUPPORTED - browser action is not supported
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FlashProgressEx(
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID KeyValue,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+)
+{
+ EFI_STATUS Status;
+
+ if (ActionRequest)
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ if(Action != EFI_BROWSER_ACTION_CHANGING)
+ return EFI_UNSUPPORTED;
+
+
+#if REFLASH_INTERACTIVE
+ if(KeyValue == FLASH_START_KEY) {
+ Status = Prologue(TRUE, FALSE);
+ if(EFI_ERROR(Status)) {
+ /* inform user, that flashing can't be performed */
+ DrawMessageBox(L"ERROR!!!!", L"Flash update failed to initialize. Press Enter key to reset system");
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ /* we have to give control back to setup browser to refresh the screen */
+ return EFI_SUCCESS;
+ }
+/* nothing to do here, wait for user response */
+ if (KeyValue != FLASH_PROGRESS_KEY) {
+ return EFI_SUCCESS;
+ }
+#else
+ Status = Prologue(FALSE, FALSE);
+ if(EFI_ERROR(Status)) {
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+#endif
+
+ Status = EFI_SUCCESS;
+
+#if FtRecovery_SUPPORT
+ if(!IsTopSwapOn()) {
+ Status = FlashWalker(TRUE);
+ }
+#endif
+
+ if(!EFI_ERROR(Status)) {
+ Status = FlashWalker(FALSE);
+ }
+
+ if(EFI_ERROR(Status)) {
+ /* something was wrong - inform user */
+ DrawMessageBox(L"ERROR!!!!", L"Flash update failed. Press Enter key to reset system");
+ pRS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+
+ Status = Epilogue();
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: SetBackUpArea
+//
+// Description: This function prepares FV_MAIN region to be backup region
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetBackUpArea(VOID)
+{
+ static BOOLEAN FirstRun = TRUE;
+ static UINT32 FlashEraser = (FLASH_ERASE_POLARITY) ? 0 : 0xffffffff;
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;
+
+ if(!FirstRun)
+ return;
+
+ FirstRun = FALSE;
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FV_MAIN_BASE;
+ Flash->Write(&(Fv->Signature), sizeof(UINT32), &FlashEraser);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiFlashBackUp
+//
+// Description: This function backs up given block from given region
+//
+// Input:
+// IN FLASH_AREA_EX *Block - flash region to work with
+// IN UINTN BlockNumber - block number within flash region
+//
+// Output:
+// EFI_SUCCESS - block saved successfully
+// EFI_ERROR - there was an error during operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiFlashBackUp(
+ IN FLASH_AREA_EX *Block,
+ IN UINTN BlockNumber
+)
+{
+ UINT8 *Source;
+ UINT8 *Destination;
+ VOID *Tmp;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ Status = pBS->AllocatePool(EfiBootServicesData, Block->BlockSize, &Tmp);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ Source = Block->BlockAddress + BlockNumber * Block->BlockSize;
+ Destination = Block->BackUpAddress + BlockNumber * Block->BlockSize;
+
+ if(Block->Type == FvTypeBootBlock)
+ SetBackUpArea();
+
+ Status = Flash->Read(Source, Block->BlockSize, Tmp);
+ if(EFI_ERROR(Status)) {
+ pBS->FreePool(Tmp);
+ return Status;
+ }
+
+//save to backup address
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ Status = Flash->Update(Destination, Block->BlockSize, Tmp);
+ pBS->RestoreTPL(OldTpl);
+
+ pBS->FreePool(Tmp);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: AmiFlashProgram
+//
+// Description: This function programs given block from given region
+//
+// Input:
+// IN FLASH_AREA_EX *Block - flash region to work with
+// IN UINTN BlockNumber - block number within flash region
+//
+// Output:
+// EFI_SUCCESS - block updated successfully
+// EFI_ERROR - there was an error during operation
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiFlashProgram(
+ IN FLASH_AREA_EX *Block,
+ IN UINTN BlockNumber
+)
+{
+ UINT8 *ImageStart;
+ UINT8 *Source;
+ UINT8 *Destination;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ ImageStart = Block->BlockAddress - FlashPartStart + RecoveryBuffer;
+ Source = ImageStart + BlockNumber * Block->BlockSize;
+ Destination = Block->BlockAddress + BlockNumber * Block->BlockSize;
+
+ OldTpl = pBS->RaiseTPL(TPL_HIGH_LEVEL);
+ Status = Flash->Update(Destination, Block->BlockSize, Source);
+ pBS->RestoreTPL(OldTpl);
+
+ return Status;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/Recovery.c b/Core/EM/Recovery/Recovery.c
new file mode 100644
index 0000000..8425fb1
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.c
@@ -0,0 +1,720 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/Recovery.c 34 8/09/12 11:10a Pats $
+//
+// $Revision: 34 $
+//
+// $Date: 8/09/12 11:10a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/Recovery.c $
+//
+// 34 8/09/12 11:10a Pats
+// [TAG] - EIP 80780
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the
+// EXT(x) file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 33 8/02/12 11:56a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c
+//
+// 32 4/20/12 2:53p Artems
+// [TAG] EIP87678
+// [Category] Improvement
+// [Description] Added function headers for CHM builder
+// [Files] Recovery.c
+//
+// 31 4/20/12 2:17p Artems
+// [TAG] EIP87678
+// [Category] New Feature
+// [Description] Selection of image to boot from on flash update boot
+// path - either old image (currently in flash) or new one in recovery
+// capsule
+// [Files] Recovery.c
+// DxeIpl.c
+// Core.sdl
+// Tokens.c
+//
+// 30 1/25/12 2:45p Pats
+// [TAG] - EIP 26909
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the NTFS
+// file system. This of necessity includes detection of GPT partitions,
+// which may contain any file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 29 11/02/11 4:52p Artems
+// EIP 74446: Fixed bug - reflash is enabled when recovery image is not
+// found
+//
+// 28 8/11/11 5:57p Artems
+// Minor fix to initialize recovery hob Address field before calling
+// ReportFV
+//
+// 27 5/13/11 4:47p Artems
+// Added secured recovery support
+//
+// 26 2/15/11 6:14p Artems
+// Fixed bug with duplicated Size variable
+//
+// 25 2/05/11 2:45p Artems
+// EIP 39463: Added support for secure update
+// EIP 39461: New ROM layout infrastructure support
+//
+// 24 10/01/10 7:40p Felixp
+// Improvement:
+// The code that detects Firmware Volumes in the recovery image
+// and publishes them is updated to use information from the ROM Layout
+// HOB.
+//
+// 23 6/11/10 11:43a Artems
+// Added porting hooks for recovery file name and validation
+//
+// 22 2/09/10 11:34a Felixp
+// ReadCapsule function update: code that verifies if FV in ROM is updated
+// to ensure that base address is below 4GB.
+//
+// 21 2/05/10 2:32p Felixp
+// Bug fix in UnknownType function.
+// The bug caused occasional hanging, when recovery image was not found.
+//
+// 20 2/05/10 8:40a Felixp
+// More flexible FV detection in the recovery image.
+//
+// 19 11/25/09 4:46p Felixp
+// sAmiRomFile renamed to RecoveryFileName
+// FlashSize renamed ro RecoveryImageSize
+//
+// 18 8/25/09 5:15p Felixp
+// Recovery module is updated to pass recovery image location via special
+// GUIDed HOB.
+// Old implementation that was relying on Firmware Volume (FV) handle,
+// required porting for a projects with non standard FV management policy.
+//
+// 17 7/09/09 12:50p Artems
+// Updated file headers
+//
+// 16 7/08/09 2:14p Robert
+// Changed the definition of the variable FlashSize from FLASH_SIZE to
+// RECOVERY_FLASH_SIZE
+//
+// 15 6/16/09 5:20p Artems
+// EIP 21169 Added Eltorito support
+//
+// 14 3/12/08 2:08p Ambikas
+// Added recovery error code for no capsule found.
+//
+// 13 8/07/07 2:21p Felixp
+// New StatusCodes added
+//
+// 12 4/13/07 6:03p Ambikas
+// Coding standard changes: updated year in AMI copyright header/footer;
+// added AMI_PHDRs for all functions; split the one line function
+// GuidMatch into several lines.
+//
+// 11 12/22/06 11:29a Felixp
+// SDL token added to customize name of the recovery ROM image
+//
+// 10 6/28/06 12:44p Felixp
+// OEM recovery type added
+//
+// 9 6/04/06 9:27p Ambikas
+//
+// 8 5/21/06 11:29p Felixp
+// Support for retries added (If recovery image not found, retry
+// RECOVERY_SCAN_RETRIES times)
+//
+// 7 4/13/06 2:02p Ambikas
+//
+// 6 4/10/06 9:50a Ambikas
+//
+// 5 3/17/06 6:10p Felixp
+// More generic calculation of the FV_MAIN offset within recovery BIOS
+// image
+//
+// 4 1/06/06 9:54a Felixp
+//
+// 1 12/01/05 9:35a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Recovery.c
+//
+// Description: Recovery functionality implementation
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+//----------------------------------------------------------------------
+
+#include <PPI/RecoveryModule.h>
+#include <AmiPeiLib.h>
+#include <Token.h>
+#include <AmiHobs.h>
+#include "Recovery.h"
+#include "RecoveryCsp.h"
+
+RECOVERY_IMAGE_HOB *pRecoveryHob;
+
+extern UINTN FlashDeviceBase;
+const CHAR8 *RecoveryFileName = CONVERT_TO_STRING(RECOVERY_ROM);
+const UINTN RecoveryImageSize = RECOVERY_IMAGE_SIZE;
+const BOOLEAN CdRecoverySupport = CD_RECOVERY_SUPPORT;
+const BOOLEAN FatRecoverySupport = FAT_RECOVERY_SUPPORT;
+const BOOLEAN NtfsRecoverySupport = NTFS_RECOVERY_SUPPORT;
+const BOOLEAN ExtRecoverySupport = EXT_RECOVERY_SUPPORT;
+
+EFI_GUID guidBlockDeviceCapsule = BLOCK_DEVICE_RECOVERY_CAPSULE_GUID;
+EFI_GUID guidSerialCapsule = SERIAL_RECOVERY_CAPSULE_GUID;
+EFI_GUID guidOemCapsule = OEM_RECOVERY_CAPSULE_GUID;
+
+#define BLOCK &guidBlockDeviceCapsule
+#define SERIAL &guidSerialCapsule
+#define CAPSULE &guidOemCapsule
+
+EFI_GUID* RecoveryDeviceOrder[] = {RECOVERY_DEVICE_ORDER, NULL};
+
+EFI_GUID guidRecoveryModule = EFI_PEI_RECOVERY_MODULE_PPI_GUID;
+EFI_GUID guidRecoveryDevice = EFI_PEI_DEVICE_RECOVERY_MODULE_PPI_GUID;
+
+EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN struct _EFI_PEI_RECOVERY_MODULE_PPI *This
+);
+
+EFI_PEI_RECOVERY_MODULE_PPI RecoveryModule = {LoadRecoveryCapsule};
+
+// PPI to be installed
+static EFI_PEI_PPI_DESCRIPTOR RecoveryPpiList[] =
+{
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidRecoveryModule, &RecoveryModule
+ }
+};
+
+EFI_PHYSICAL_ADDRESS RecoveryBuffer = NULL;
+UINTN RecoveryBufferSize = 0;
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: VerifyFwImage
+//
+// Description: Verifies recovery capsule
+//
+// Note: This is dummy function. Actual implementation is in SecureFlash pkg
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS VerifyFwImage (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID **Buffer,
+ IN OUT UINT32 *Size,
+ OUT UINT32 *FailedTask
+)
+#if defined(SecFlashUpd_SUPPORT) && SecFlashUpd_SUPPORT == 1
+;
+#else
+{
+ if(FailedTask)
+ *FailedTask = 0;
+ return EFI_SUCCESS;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadCapsule
+//
+// Description: Called by FindRecoveryDevice. Calls LoadRecoveryCapsule
+// function of the passed in ppi EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+// to get recovery image. If found, an HOB is created for this
+// recovery image.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+EFI_STATUS ReadCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *pDRM,
+ UINTN CapsuleInstance, UINTN Size
+)
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS RomImageStart = FlashDeviceBase;
+ UINT32 FailedStage;
+
+ if(Size > RecoveryBufferSize){
+ Status = (*PeiServices)->AllocatePages(PeiServices, EfiBootServicesCode, (Size >> 12) + 1, &RecoveryBuffer);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ RecoveryBufferSize = Size;
+ }
+
+ PEI_TRACE((TRACE_DXEIPL, PeiServices, "Loading Recovery Image..."));
+
+ Status = pDRM->LoadRecoveryCapsule(PeiServices, pDRM, CapsuleInstance, (VOID*)RecoveryBuffer);
+
+ PEI_TRACE((TRACE_DXEIPL, PeiServices, "done. Status: %r\n",Status));
+
+ if (EFI_ERROR(Status))
+ return Status;
+
+ Status = VerifyFwImage(PeiServices, (VOID**)&RecoveryBuffer, (UINT32*)&Size, (UINT32*)&FailedStage );
+ pRecoveryHob->FailedStage = FailedStage;
+ pRecoveryHob->Status = (UINT8)Status;
+ if (EFI_ERROR(Status )) {
+ PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_INVALID_CAPSULE, EFI_ERROR_MAJOR | Status );
+ return Status;
+ }
+
+ pRecoveryHob->Address = RecoveryBuffer;
+
+ return Status;
+}
+
+typedef BOOLEAN (*PREDICATE)(EFI_GUID *pType, VOID* pContext);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: FindRecoveryDevice
+//
+// Description: Called by LoadRecoveryCapsule.
+// Loop: Locate all installed EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+// ppis and call ReadCapsule on them.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS FindRecoveryDevice(
+ IN EFI_PEI_SERVICES **PeiServices,
+ PREDICATE Criteria, VOID* pContext
+){
+ EFI_STATUS Status = EFI_SUCCESS;
+ BOOLEAN Loaded = FALSE;
+ UINTN i = 0;
+
+ do {
+ EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *pRecoveryDevice;
+ EFI_PEI_PPI_DESCRIPTOR *pDummy;
+ UINTN j, n;
+
+ Status = (*PeiServices)->LocatePpi(PeiServices, &guidRecoveryDevice, i++, &pDummy, &pRecoveryDevice);
+ if (EFI_ERROR(Status))
+ break;
+
+ Status = pRecoveryDevice->GetNumberRecoveryCapsules(PeiServices, pRecoveryDevice, &n);
+ if (EFI_ERROR(Status))
+ continue;
+
+ for(j = 0; j < n; j++) {
+ UINTN Size;
+ EFI_GUID CapsuleType;
+
+ Status = pRecoveryDevice->GetRecoveryCapsuleInfo(PeiServices, pRecoveryDevice, j, &Size, &CapsuleType);
+ if (EFI_ERROR(Status) || !Criteria(&CapsuleType, pContext))
+ continue;
+
+ Status = ReadCapsule(PeiServices, pRecoveryDevice, j, Size);
+ if (!EFI_ERROR(Status)){
+ Loaded = TRUE;
+ PEI_PROGRESS_CODE(PeiServices,PEI_RECOVERY_CAPSULE_LOADED);
+ break;
+ }
+ }
+ } while(!Loaded);
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GuidMatch
+//
+// Description: Wrapper for guidcmp function.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GuidMatch(EFI_GUID* Type1, EFI_GUID* Type2)
+{
+ return !guidcmp(Type1,Type2);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: UnknownType
+//
+// Description: Returns TRUE if the parameter, guid CapsuleType, in not
+// in parameter, List (a list of guids).
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN UnknownType(EFI_GUID* CapsuleType, EFI_GUID** List)
+{
+ EFI_GUID **pType;
+ for(pType = List; *pType; pType++) if (!guidcmp(*pType,CapsuleType)) return FALSE;
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: LoadRecoveryCapsule
+//
+// Description: LoadRecoveryCapsule function of EFI_PEI_RECOVERY_MODULE_PPI
+// ppi. RecoveryDeviceOrder is a list of guids; each guid
+// represents a type of recovery device. We go through
+// this list and call FindRecoveryDevice for each type of
+// device.
+// -This function should not be confused with LoadRecoveryCapsule
+// function of the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI ppi.
+// -Called by DxeIpl.
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS LoadRecoveryCapsule(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN struct _EFI_PEI_RECOVERY_MODULE_PPI *This
+)
+{
+ EFI_GUID **ppType;
+ EFI_STATUS Status = EFI_NOT_FOUND;
+ UINTN i;
+ EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+
+ PEI_PROGRESS_CODE(PeiServices,PEI_RECOVERY_STARTED);
+
+// Create Recovery Hob
+ Status = (*PeiServices)->CreateHob(
+ PeiServices, EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof(RECOVERY_IMAGE_HOB), &pRecoveryHob);
+
+ if (EFI_ERROR(Status))
+ return Status;
+
+ pRecoveryHob->Header.Name = RecoveryHobGuid;
+ pRecoveryHob->Address = NULL;
+ pRecoveryHob->FailedStage = 0;
+
+ for(i = 0; i < RECOVERY_SCAN_RETRIES; i++) {
+ for(ppType = RecoveryDeviceOrder; *ppType; ppType++) {
+ Status = FindRecoveryDevice(PeiServices,GuidMatch,*ppType);
+ if (!EFI_ERROR(Status))
+ return Status;
+ }
+
+ Status = FindRecoveryDevice(PeiServices, UnknownType, RecoveryDeviceOrder);
+ if (!EFI_ERROR(Status)) break;
+ }
+
+ if (EFI_ERROR(Status)) {
+ PEI_ERROR_CODE(PeiServices, PEI_RECOVERY_NO_CAPSULE, EFI_ERROR_MAJOR);
+ pRecoveryHob->Status = (UINT8)Status;
+ }
+
+ return Status;
+}
+
+//this funciton is created from InitList.c template file during build process
+VOID InitParts(IN EFI_FFS_FILE_HEADER *FfsHeader,IN EFI_PEI_SERVICES **PeiServices);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: RecoveryEntry
+//
+// Description: Entry point. Installs EFI_PEI_RECOVERY_MODULE_PPI ppi
+// (which has function LoadRecoveryCapsule).
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS RecoveryEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ InitParts(FfsHeader,PeiServices);
+ return (*PeiServices)->InstallPpi(PeiServices,RecoveryPpiList);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemGetFileListFromPrimaryVolume
+//
+// Description: Porting hook to return recovery capsule file name from CD
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemGetFileListFromPrimaryVolume(
+ IN DIR_RECORD *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_RECORD **Buffer
+);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemGetFileListFromFatVolume
+//
+// Description: Porting hook to return recovery capsule file name from FAT
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemGetFileListFromFatVolume(
+ IN DIR_ENTRY *Root,
+ IN UINT32 RootEntries,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY **Buffer
+);
+
+
+#if NTFS_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemGetFileListFromNtfsVolume
+//
+// Description: Porting hook to return recovery capsule file name from NTFS
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemGetFileListFromNtfsVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT INDEX_ENTRY **Buffer
+);
+#endif
+
+#if EXT_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemGetFileListFromExtVolume
+//
+// Description: Porting hook to return recovery capsule file name from EXT(n)
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemGetFileListFromExtVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY_EXT **Buffer
+);
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemIsValidFile
+//
+// Description: Porting hook to validate recovery capsule file
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN OemIsValidFile(
+ IN VOID *FileData,
+ IN UINTN FileSize
+);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFileListFromPrimaryVolume
+//
+// Description: Wrapper for porting hook OemGetFileListFromPrimaryVolume
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetFileListFromPrimaryVolume(
+ IN DIR_RECORD *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_RECORD **Buffer
+)
+{
+ OemGetFileListFromPrimaryVolume(Root, RootSize, NumberOfFiles, Buffer);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFileListFromFatVolume
+//
+// Description: Wrapper for porting hook OemGetFileListFromFatVolume
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetFileListFromFatVolume(
+ IN DIR_ENTRY *Root,
+ IN UINT32 RootEntries,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY **Buffer
+)
+{
+ OemGetFileListFromFatVolume(Root, RootEntries, NumberOfFiles, Buffer);
+}
+
+#if NTFS_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFileListFromNtfsVolume
+//
+// Description: Wrapper for porting hook OemGetFileListFromNtfsVolume
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetFileListFromNtfsVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT INDEX_ENTRY **Buffer
+)
+{
+ OemGetFileListFromNtfsVolume(Root, RootSize, NumberOfFiles, Buffer);
+}
+#endif
+
+#if EXT_RECOVERY_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetFileListFromExtVolume
+//
+// Description: Wrapper for porting hook OemGetFileListFromExtVolume
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID GetFileListFromExtVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY_EXT **Buffer
+)
+{
+ OemGetFileListFromExtVolume(Root, RootSize, NumberOfFiles, Buffer);
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: IsValidFile
+//
+// Description: Wrapper for porting hook OemIsValidFile
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN IsValidFile(
+ IN VOID *FileData,
+ IN UINTN FileSize
+)
+{
+ return OemIsValidFile(FileData, FileSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: OemGetRecoveryFileInfo
+//
+// Description: Porting hook to return recovery capsule filename and size
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS OemGetRecoveryFileInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+);
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetRecoveryFileInfo
+//
+// Description: Wrapper for porting hook OemGetRecoveryFileInfo
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetRecoveryFileInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+)
+{
+ if(pCapsuleName != NULL)
+ *pCapsuleName = (CHAR8 *)RecoveryFileName;
+
+ if(pCapsuleSize != NULL)
+ *pCapsuleSize = (UINTN)RecoveryImageSize;
+
+ if(ExtendedVerification != NULL)
+ *ExtendedVerification = FALSE;
+
+ return OemGetRecoveryFileInfo(PeiServices, pCapsuleName, pCapsuleSize, ExtendedVerification);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: AmiGetRecoveryFileInfo
+//
+// Description: Default porting hook value for OemGetRecoveryFileInfo
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS AmiGetRecoveryFileInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+)
+{
+ return EFI_SUCCESS;
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
diff --git a/Core/EM/Recovery/Recovery.cif b/Core/EM/Recovery/Recovery.cif
new file mode 100644
index 0000000..b5b1a7d
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "Recovery"
+ category = ModulePart
+ LocalRoot = "Core\EM\Recovery\"
+ RefName = "Recovery"
+[files]
+"Recovery.sdl"
+"Recovery.mak"
+"Recovery.c"
+"Recovery.h"
+"Recovery.dxs"
+"RecoveryCsp.h"
+[parts]
+"ReFlash"
+"RecoveryPpi"
+<endComponent>
diff --git a/Core/EM/Recovery/Recovery.dxs b/Core/EM/Recovery/Recovery.dxs
new file mode 100644
index 0000000..6dfec9f
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.dxs
@@ -0,0 +1,57 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/Recovery.dxs 1 12/01/05 9:35a Felixp $
+//
+// $Revision: 1 $
+//
+// $Date: 12/01/05 9:35a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/Recovery.dxs $
+//
+// 1 12/01/05 9:35a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Recovery.dxs
+//
+// Description: Dependancy expression for the component
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <PPI/LoadFile.h>
+DEPENDENCY_START
+EFI_PEI_FV_FILE_LOADER_GUID
+AND
+EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI
+AND
+EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI
+DEPENDENCY_END
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2005, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 6145-F Northbelt Pkwy, Norcross, GA 30071 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/Recovery.h b/Core/EM/Recovery/Recovery.h
new file mode 100644
index 0000000..d6376b6
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.h
@@ -0,0 +1,113 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/Recovery.h 10 8/02/12 11:54a Artems $
+//
+// $Revision: 10 $
+//
+// $Date: 8/02/12 11:54a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/Recovery.h $
+//
+// 10 8/02/12 11:54a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c
+//
+// 9 5/13/11 4:46p Artems
+// Removed RecoveryCapsuleName and RecoveryCapsuleSize constants
+// All recovery modules should use GetRecoveryFileInfo instead
+//
+// 8 11/25/09 4:46p Felixp
+// sAmiRomFile renamed to RecoveryFileName
+// FlashSize renamed ro RecoveryImageSize
+//
+// 7 7/08/09 6:23p Artems
+// Changed file header, minor code clean-up
+//
+// 6 6/16/09 5:21p Artems
+// EIP 21169 Added Eltorito support
+//
+// 5 4/13/07 6:04p Ambikas
+// Coding standard changes: udpated the year in the AMI copyright
+// header/footer.
+//
+// 4 6/28/06 12:44p Felixp
+// OEM recovery type added
+//
+// 3 4/13/06 2:03p Ambikas
+//
+// 2 4/10/06 9:51a Ambikas
+//
+// 1 12/01/05 9:35a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Recovery.h
+//
+// Description: Recovery devices guid definition
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#ifndef __RECOVERY__H__
+#define __RECOVERY__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <PPI/DeviceRecoveryModule.h>
+#include <PPI/DeviceRecoveryBlockIo.h>
+
+//Serial port recovery
+#define SERIAL_RECOVERY_CAPSULE_GUID \
+ { 0x699add70, 0x8554, 0x4993, { 0x83, 0xf6, 0xd2, 0xcd, 0xc0, 0x81, 0xdd, 0x85 } }
+
+//Recovery from mass storage device with FAT file system
+#define BLOCK_DEVICE_RECOVERY_CAPSULE_GUID \
+ { 0xba8263c, 0xa8bd, 0x4aad, { 0xb4, 0x2, 0x6a, 0x6a, 0xf2, 0xf7, 0xe7, 0x7d } }
+
+// OEM Recovery
+// {595A6EDC-6D2C-474a-9082-3B992851DFFE}
+#define OEM_RECOVERY_CAPSULE_GUID \
+ { 0x595a6edc, 0x6d2c, 0x474a, { 0x90, 0x82, 0x3b, 0x99, 0x28, 0x51, 0xdf, 0xfe } }
+
+extern EFI_GUID guidRecoveryDevice;
+extern EFI_GUID guidBlockDeviceCapsule;
+extern EFI_GUID guidSerialCapsule;
+extern EFI_GUID guidOemCapsule;
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file
diff --git a/Core/EM/Recovery/Recovery.mak b/Core/EM/Recovery/Recovery.mak
new file mode 100644
index 0000000..0ab43c3
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.mak
@@ -0,0 +1,116 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/Recovery.mak 1 5/17/13 8:01a Thomaschen $
+#
+# $Revision: 1 $
+#
+# $Date: 5/17/13 8:01a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/Recovery.mak $
+#
+# 1 5/17/13 8:01a Thomaschen
+# Update for EIP124189.
+#
+# 8 8/09/12 11:11a Pats
+# [TAG] - EIP 80780
+# [Category] - Function Request
+# [Description] - Support for recovery from media formatted with the
+# EXT(x) file system.
+# [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+# and FsRecovery.c (source)
+#
+# 7 1/25/12 2:46p Pats
+# [TAG] - EIP 26909
+# [Category] - Function Request
+# [Description] - Support for recovery from media formatted with the NTFS
+# file system. This of necessity includes detection of GPT partitions,
+# which may contain any file system.
+# [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+# and FsRecovery.c (source)
+#
+# 6 5/13/11 4:44p Artems
+# Replaced GetFileName infrastructure with GetRecoveryFileInfo for
+# clarification
+#
+# 5 2/05/11 2:43p Artems
+# EIP 39463: Integrated Core portion for secure update - eLink support
+# for GetFileName
+#
+# 4 6/11/10 11:42a Artems
+# Added porting hooks for recovery file name and validation
+#
+# 3 7/08/09 6:21p Artems
+# Changed file header
+#
+# 2 12/02/05 11:17a Felixp
+#
+# 1 12/01/05 9:35a Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: Recovery.mak
+#
+# Description: Makefile for recovery module
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : Recovery
+
+AMI_CSP_LIB_INCLUDE_FILES = "$(Recovery_DIR)\RecoveryCsp.h" + \
+$(AMI_CSP_LIB_INCLUDE_FILES)
+
+RECOVERY_DEFINES =\
+/DOemGetFileListFromPrimaryVolume=$(OemGetFileListFromPrimaryVolumeFunction) \
+/DOemGetFileListFromFatVolume=$(OemGetFileListFromFatVolumeFunction) \
+/DOemGetFileListFromNtfsVolume=$(OemGetFileListFromNtfsVolumeFunction) \
+/DOemGetFileListFromExtVolume=$(OemGetFileListFromExtVolumeFunction) \
+/DOemIsValidFile=$(OemIsValidFileFunction) \
+!IF $(PfatServices_SUPPORT) == 1
+/DOemGetRecoveryFileInfo=PfatImageInfo
+!ELSE
+/DOemGetRecoveryFileInfo=$(OemGetRecoveryFileInfoFunction)
+!ENDIF
+
+Recovery : $(BUILD_DIR)\Recovery.mak RecoveryBin
+
+$(BUILD_DIR)\Recovery.mak : $(Recovery_DIR)\$(@B).cif $(Recovery_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(Recovery_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+RecoveryBin : $(AMIPEILIB) $(RECOVERYLIB)
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\Recovery.mak all\
+ GUID=E008B434-0E73-440c-8612-A143F6A07BCB\
+ "MY_DEFINES=$(RECOVERY_DEFINES)"\
+ ENTRY_POINT=RecoveryEntry\
+ "INIT_LIST=$(RecoveryInitialize)"\
+ TYPE=PEIM COMPRESS=1
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/Recovery/Recovery.sdl b/Core/EM/Recovery/Recovery.sdl
new file mode 100644
index 0000000..c735c00
--- /dev/null
+++ b/Core/EM/Recovery/Recovery.sdl
@@ -0,0 +1,235 @@
+TOKEN
+ Name = "Recovery_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Recovery support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "RECOVERY_DEVICE_ORDER"
+ Value = "CAPSULE, BLOCK, SERIAL"
+ Help = "Defines order in which devices will be searched \for the recovery image."
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FAT_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SEARCH_FAT_PATH"
+ Value = "0"
+ Help = "If ON, a path may be specified in the token RECOVERY_ROM. \For FAT file system only."
+ TokenType = BOOLEAN
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "NTFS_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "EXT_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CD_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ATAPI_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "SERIAL_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "ATA_RECOVERY_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "RECOVERY_SCAN_RETRIES"
+ Value = "3"
+ Help = "Number of times to scan all recovery devices before reporting error"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "RECOVERY_ROM"
+ Value = "$(AMI_ROM)"
+ TokenType = Expression
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "RECOVERY_IMAGE_SIZE"
+ Value = "$(FLASH_SIZE)"
+ Help = "This is the size of the recovery file used in the build process"
+ TokenType = Integer
+ TargetH = Yes
+End
+
+PATH
+ Name = "Recovery_DIR"
+End
+
+MODULE
+ Help = "Includes Recovery.mak to Project"
+ File = "Recovery.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\Recovery.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RECOVERYLIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(Recovery_DIR)\Recovery.lib"
+ Parent = "RECOVERYLIB"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "RecoveryInitialize"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "CapsuleDeviceRecoveryEntry,"
+ Parent = "RecoveryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "BlockDeviceRecoveryEntry,"
+ Parent = "RecoveryInitialize"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "SerialRecoveryPeimEntry,"
+ Parent = "RecoveryInitialize"
+ Token = "SERIAL_RECOVERY_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "Atapi_RecoveryPeimEntry,"
+ Parent = "RecoveryInitialize"
+ Token = "ATAPI_RECOVERY_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "Ata_RecoveryPeimEntry,"
+ Parent = "RecoveryInitialize"
+ Token = "ATA_RECOVERY_SUPPORT" "=" "1"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "OemGetFileListFromPrimaryVolumeFunction"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "AmiGetFileListFromPrimaryVolume"
+ Parent = "OemGetFileListFromPrimaryVolumeFunction"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "OemGetFileListFromFatVolumeFunction"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "AmiGetFileListFromFatVolume"
+ Parent = "OemGetFileListFromFatVolumeFunction"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "OemGetFileListFromNtfsVolumeFunction"
+ InvokeOrder = ReplaceParent
+ Token = "NTFS_RECOVERY_SUPPORT" "=" "1"
+End
+
+ELINK
+ Name = "AmiGetFileListFromNtfsVolume"
+ Parent = "OemGetFileListFromNtfsVolumeFunction"
+ InvokeOrder = AfterParent
+ Token = "NTFS_RECOVERY_SUPPORT" "=" "1"
+End
+
+ELINK
+ Name = "OemGetFileListFromExtVolumeFunction"
+ InvokeOrder = ReplaceParent
+ Token = "EXT_RECOVERY_SUPPORT" "=" "1"
+End
+
+ELINK
+ Name = "AmiGetFileListFromExtVolume"
+ Parent = "OemGetFileListFromExtVolumeFunction"
+ InvokeOrder = AfterParent
+ Token = "EXT_RECOVERY_SUPPORT" "=" "1"
+End
+
+ELINK
+ Name = "OemIsValidFileFunction"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "AmiIsValidFile"
+ Parent = "OemIsValidFileFunction"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "OemGetRecoveryFileInfoFunction"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "AmiGetRecoveryFileInfo"
+ Parent = "OemGetRecoveryFileInfoFunction"
+ InvokeOrder = AfterParent
+End
diff --git a/Core/EM/Recovery/RecoveryCsp.h b/Core/EM/Recovery/RecoveryCsp.h
new file mode 100644
index 0000000..8460371
--- /dev/null
+++ b/Core/EM/Recovery/RecoveryCsp.h
@@ -0,0 +1,849 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//*************************************************************************
+// $Header: /Alaska/BIN/Core/Modules/Recovery/RecoveryCsp.h 5 8/09/12 11:12a Pats $
+//
+// $Revision: 5 $
+//
+// $Date: 8/09/12 11:12a $
+//*************************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/BIN/Core/Modules/Recovery/RecoveryCsp.h $
+//
+// 5 8/09/12 11:12a Pats
+// [TAG] - EIP 80780
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the
+// EXT(x) file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 4 1/25/12 2:47p Pats
+// [TAG] - EIP 26909
+// [Category] - Function Request
+// [Description] - Support for recovery from media formatted with the NTFS
+// file system. This of necessity includes detection of GPT partitions,
+// which may contain any file system.
+// [Files] Recovery.c, Recovery.mak, Recovery.sdl, RecoveryCsp.h (bin),
+// and FsRecovery.c (source)
+//
+// 3 5/13/11 4:44p Artems
+// Replaced GetFileName infrastructure with GetRecoveryFileInfo for
+// clarification
+//
+// 2 2/05/11 2:46p Artems
+// EIP 39463: Added support for secure update - GetFileName eLink
+//
+// 1 6/11/10 11:45a Artems
+// Definitions of layout for FAT and ISO9660 structures
+//
+//*************************************************************************
+//<AMI_FHDR_START>
+//
+// Name: RecoveryCsp.h
+//
+// Description:
+// File system recovery data types definition
+//
+//<AMI_FHDR_END>
+//*************************************************************************
+#ifndef __RECOVERY_CSP__H__
+#define __RECOVERY_CSP__H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <PPI/DeviceRecoveryBlockIo.h>
+
+#define FAT12 0
+#define FAT16 1
+#define FAT32 2
+#define NTFS 3
+#define EXTx 4
+
+//
+// Some NTFS definitions
+//
+#define FILE_RECORD_SIZE 1024 // Size of an NTFS file record
+#define MAXIMUM_RECORD_NUMBER 0x0000FFFFFFFFFFFF // NTFS max record no.
+#define FR_ATTRIBUTE_NAME 0x00000030
+#define FR_ATTRIBUTE_VOLUME_NAME 0x00000060
+#define FR_ATTRIBUTE_DATA 0x00000080
+#define FR_ATTRIBUTE_INDEX_ROOT 0x00000090
+#define FR_ATTRIBUTE_INDEX_ALLOC 0x000000A0
+#define MINIMUM_ENTRY_SIZE 0x58
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+ CHAR8 FileName[11];
+ UINT8 Unused[3]; //Attr, NTRes, CrtTimeTenth;
+ UINT16 Unused1[3]; //CrtTime, CrtDate, LstAccDate;
+ UINT16 FirstClusterHi;
+ UINT16 Unused2[2]; //WrtTime, WrtDate;
+ UINT16 FirstClusterLo;
+ UINT32 FileSize;
+} DIR_ENTRY;
+
+typedef struct
+{
+ UINT8 jmp[3]; //0
+ CHAR8 OEMName[8]; //3
+ UINT16 BytsPerSec; //11
+ UINT8 SecPerClus; //13
+ UINT16 RsvdSecCnt; //14
+ UINT8 NumFATs; //16
+ UINT16 RootEntCnt; //17
+ UINT16 TotSec16; //19
+ UINT8 Media; //21
+ UINT16 FATSz16; //22
+ UINT16 SecPerTrk; //24
+ UINT16 NumHeads; //26
+ UINT32 HiddSec; //28
+ UINT32 TotSec32; //32
+ union
+ {
+ struct
+ {
+ UINT8 Padding[510 - 36];
+ } Fat16;
+ struct
+ {
+ UINT32 FATSz32; //36
+ UINT8 Padding1[4]; //40
+ UINT32 RootClus; //44
+ UINT8 Padding2[510 - 48];
+ } Fat32;
+ struct
+ {
+ UINT32 FATSz32u; //36
+ UINT64 TotSec64; //40
+ UINT64 MFTClus; //48
+ UINT8 Padding3[510 - 56];
+ } Ntfs;
+ } Fat;
+ UINT16 Signature;
+} BOOT_SECTOR;
+
+typedef struct _RC_VOL_INFO
+{
+ UINT32 BlockSize;
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlkIo;
+ UINTN Device;
+ UINT8 FatType;
+ UINT8 *FatPointer;
+ DIR_ENTRY *RootPointer;
+ UINT64 PartitionOffset;
+ UINT64 FatOffset;
+ UINT64 RootOffset;
+ UINT64 DataOffset;
+ UINT32 BytesPerCluster;
+} RC_VOL_INFO;
+
+typedef struct
+{
+ UINT8 Length, ExtAttrLength; //1,2
+ UINT32 ExtentOffset, Unused1; //3..10
+ UINT32 DataLength, Unused2; //11..18
+ UINT8 DataTime[7]; //19..25
+ UINT8 Flags; //26
+ UINT8 Unused3[32 - 26]; //27..32
+ UINT8 LengthOfFileId; //33
+} DIR_RECORD;
+
+typedef struct
+{
+ UINT8 Type; //1
+ CHAR8 StandardId[5]; //2..6
+ UINT8 Version; //7
+ UINT8 Unused1[156 - 7]; //8..156
+ DIR_RECORD RootDir; //157..190
+ UINT8 Padding;
+ CHAR8 Unused2[2048 - 190]; //191..2048
+} PRIMARY_VOLUME_DESCRIPTOR;
+
+typedef struct
+{
+ UINT8 BootRecordIndicator;
+ CHAR8 ISO9660Identifier[0x5];
+ UINT8 DescriptorVersion;
+ CHAR8 BootSystemIdentifier[0x20];
+ CHAR8 Unused0[0x20];
+ UINT32 BootCatalogFirstSector;
+ UINT8 Unused1[0x7B6];
+} BOOT_RECORD_VOLUME_DESCRIPTOR;
+
+typedef struct
+{
+ UINT8 HeaderID;
+ UINT8 PlatformID;
+ UINT8 Reserved0[0x2];
+ CHAR8 ManufacturerID[0x18];
+ UINT16 Checksum;
+ UINT16 Key;
+} VALIDATION_ENTRY;
+
+typedef struct
+{
+ UINT8 BootIndicator;
+ UINT8 BootMediaType;
+ UINT16 LoadSegment;
+ UINT8 SystemType;
+ UINT8 Unused0;
+ UINT16 SectorCount;
+ UINT32 LoadRBA;
+ UINT8 Unused1[0x14];
+} INITIAL_DEFAULT_ENTRY;
+
+typedef struct _MBR_PARTITION
+{
+ UINT8 BootIndicator;
+ UINT8 StartHead;
+ UINT8 StartSector;
+ UINT8 StartTrack;
+ UINT8 OSType;
+ UINT8 EndHead;
+ UINT8 EndSector;
+ UINT8 EndTrack;
+ UINT32 StartingLba;
+ UINT32 SizeInLba;
+} MBR_PARTITION;
+
+typedef struct _MASTER_BOOT_RECORD
+{
+ UINT8 BootCode[440];
+ UINT32 UniqueMbrSig;
+ UINT16 Unknown;
+ MBR_PARTITION PartRec[4];
+ UINT16 Sig;
+} MASTER_BOOT_RECORD;
+
+//
+// GUID Partition structures
+//
+typedef struct _GUID_PARTITION
+{
+ UINT8 TypeGuid[16];
+ UINT8 UniqueGuid[16];
+ UINT64 FirstLba;
+ UINT64 LastLba;
+ UINT64 Flags;
+ CHAR16 Name[36];
+} GUID_PARTITION;
+
+typedef struct _GUID_BOOT_RECORD
+{
+ GUID_PARTITION GuidPart[4];
+} GUID_BOOT_RECORD;
+
+typedef struct _GUID_TABLE_HEADER
+{
+ UINT8 Signature[8];
+ UINT32 Revision;
+ UINT32 HeaderSize;
+ UINT32 HeaderCRC;
+ UINT32 Reserved;
+ UINT64 CurrentLBA;
+ UINT64 BackupLBA;
+ UINT64 FirstLBA;
+ UINT64 LastLBA;
+ UINT8 DiskGuid[16];
+ UINT64 StartLBA;
+ UINT32 EntryCount;
+ UINT32 EntrySize;
+ UINT32 ArraySize;
+} GUID_TABLE_HEADER;
+
+//
+// NTFS Structures
+//
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MFT_FILE_RECORD
+//
+// Description: Structure of a Master File Table file record.
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _MFT_FILE_RECORD
+{
+ CHAR8 FR_Name[4]; // 0x00 - Always "FILE"
+ UINT16 FR_UpdateSeqOffset; // 0x04
+ UINT16 FR_UpdateSeqSize; // 0x06
+ UINT64 FR_LogSeqNumber; // 0x08
+ UINT16 FR_SequenceNumber; // 0x10
+ UINT16 FR_HardLinkCount; // 0x12
+ UINT16 FR_AttributeOffset; // 0x14 - Offset to Attributes
+ UINT16 FR_Flags; // 0x16 - File Record Flags
+ // 0x01 - Record is in use
+ // 0x02 - Record is a directory
+ UINT32 FR_RealSize; // 0x18 - Real size of record
+ UINT32 FR_AllocatedSize; // 0x1C - Allocated size of record
+ UINT64 FR_BaseRecordNumber; // 0x20 - Zero if this is a base record
+} MFT_FILE_RECORD;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_ATTR_HEADER_RES
+//
+// Description: Structure of a File Record resident attribute header.
+//
+// Referrals:
+//
+// Note(s): The "Name" in this structure is not a file name, but the
+// name of the attribute. Not used in this driver.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _FR_ATTR_HEADER_RES
+{
+ UINT32 AHR_Type; // 0x00 - Attribute Type
+ // 0x30 - File Name
+ // 0x80 - Data
+ UINT32 AHR_Length; // 0x04 - Attribute Length
+ UINT8 AHR_NonResFlag; // 0x08 - Non-Resident Flag
+ UINT8 AHR_NameLength; // 0x09 - Name Length (if named)
+ UINT16 AHR_NameOffset; // 0x0A - Offset to Name (if named)
+ UINT16 AHR_Flags; // 0x0C - Attribute Hdr. Flags
+ // 0x0001 - Compressed
+ // 0x4000 - Encrypted
+ // 0x8000 - Sparse
+ UINT16 AHR_AttributeId; // 0x0E
+ UINT32 AHR_InfoLength; // 0x10 - Attribute Information Length
+ UINT16 AHR_InfoOffset; // 0x14 - Offset to this Attribute's
+ // Information
+ UINT16 AHR_IndexFlag; // 0x16
+} FR_ATTR_HEADER_RES;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_ATTR_HEADER_NONRES
+//
+// Description: Structure of a File Record non-resident attribute header.
+//
+// Referrals:
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _FR_ATTR_HEADER_NONRES
+{
+ UINT32 AHNR_Type; // 0x00 - Attribute Type
+ // 0x30 - File Name
+ // 0x80 - Data
+ UINT32 AHNR_Length; // 0x04 - Attribute Length
+ UINT8 AHNR_NonResFlag; // 0x08 - Non-Resident Flag
+ UINT8 AHNR_NameLength; // 0x09 - Name Length (if named)
+ UINT16 AHNR_NameOffset; // 0x0A - Offset to Name (if named)
+ UINT16 AHNR_Flags; // 0x0C - Flags
+ // 0x0001 - Compressed
+ // 0x4000 - Encrypted
+ // 0x8000 - Sparse
+ UINT16 AHNR_AttributeId; // 0x0E
+ UINT64 AHNR_StartingVCN; // 0x10 - Staeting Virtual Cluster Number
+ UINT64 AHNR_LastVCN; // 0x18 - Last Virtual Cluster Number
+ UINT16 AHNR_RunOffset; // 0x20 - Offset to data runs
+ // (Usually 0x40 for a
+ // Data attribute)
+} FR_ATTR_HEADER_NONRES;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_NAME_ATTRIBUTE (0x30)
+//
+// Description: Structure of a Master File Table Name Attribute.
+//
+// Referrals:
+//
+// Notes: Time stamps in NTFS are the number of 100ns units since
+// January 1, 1601.
+// This attribute is preceeded by a resident attribute header.
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _FR_NAME_ATTRIBUTE
+{
+ UINT64 NA_PDReference; // 0x00 - Parent Directory Reference
+ UINT64 NA_CreationTime; // 0x08 - File Creation Time
+ UINT64 NA_AlteredTime; // 0x10 - File Altered Time
+ UINT64 NA_MFTChangedTime; // 0x18 - MFT Record Changed Time
+ UINT64 NA_ReadTime; // 0x20 - File Read Time
+ UINT64 NA_AllocatedSize; // 0x28 - Allocated Size of File
+ UINT64 NA_RealSize; // 0x30 - Real size of File
+ UINT32 NA_Flags; // 0x38 - File Flags
+ // Note: These flags correspond to
+ // DOS flags up to 0x20 (Archive).
+ // If other flags are set, reject
+ // the file.
+ UINT32 NA_Reparse; // 0x3C
+ UINT8 NA_NameLength; // 0x40 - Length of file name in Words
+ UINT8 NA_NameType; // 0x41 - File Name type
+ // 0x00 - POSIX
+ // 0x01 - Unicode
+ // 0x02 - DOS
+ // 0x03 - Both
+ CHAR16 NA_Name[1]; // 0x42 - File Name (unicode)
+} FR_NAME_ATTRIBUTE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_DATA_ATTRIBUTE (0x80)
+//
+// Description: Structure of a Master File Table Data Attribute.
+//
+// Referrals:
+//
+// Notes: This attribute can be preceeded by a resident or non-resident
+// attribute header. If resident, the data will be the actual
+// file data. If non-resident, the data will be a run list
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _FR_DATA_ATTRIBUTE
+{
+ UINT8 DA_Data[1]; // 0x00 - Run List or data
+} FR_DATA_ATTRIBUTE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_INDEX_ROOT_ATTRIBUTE (0x90)
+//
+// Description: Structure of a Master File Table Index Root Attribute.
+//
+// Referrals:
+//
+// Notes: A small index will have it's entries inside this attribute.
+// This attribute is preceeded by a resident attribute header.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+typedef struct _FR_INDEX_ROOT_ATTRIBUTE
+{
+ UINT32 IRA_Type;
+ UINT32 IRA_Collation;
+ UINT32 IRA_Size;
+ UINT8 IRA_ClustersPerIndexRec;
+ UINT8 Padding1[3];
+ UINT32 IRA_Offset; // 0x10 - Offset to Index entries (if small index)
+ // The above offset is from here,
+ // not from beginning.
+ UINT32 IRA_TotalSize;
+ UINT32 IRA_AllocSize;
+ UINT8 IRA_Flags; // 0x1C - 0 = small index, 1 = large index
+ UINT8 Padding2[3];
+} FR_INDEX_ROOT_ATTRIBUTE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: FR_INDEX_ALLOC_ATTRIBUTE (0xA0)
+//
+// Description: Structure of a Master File Table Index Allocation Attribute.
+//
+// Referrals:
+//
+// Notes: A large index will be in a separate index file, and the
+// run list in this attribute will indicate where it is.
+// This attribute is preceeded by a non-resident attribute header
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+typedef struct _FR_INDEX_ALLOC_ATTRIBUTE
+{
+ UINT8 IAA_RunList[1]; // 0x00 - Run list of index record
+} FR_INDEX_ALLOC_ATTRIBUTE;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: INDEX_RECORD
+//
+// Description: Structure of an Index record.
+//
+// Referrals:
+//
+// Notes: In NTFS, the Index is equivalent to a directory in FAT. A large
+// index will be contained in an Index Record, while a small index
+// will be contained within the Master File Table File Record for
+// the index, in the Index Root Attribute. Index Records are
+// files, the way FAT directories are files, but not every
+// "directory" will have a file. See the structure INDEX_ENTRY
+// for the actual "directory entry" format.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+typedef struct _INDEX_RECORD
+{
+ CHAR8 INDR_Name[4]; // 0x00 - Always "INDX"
+ UINT16 INDR_UpSeqOff; // 0x04 - Offset to update sequence
+ UINT16 INDR_UpSeqSize; // 0x06 - Size of update sequence
+ UINT64 INDR_LogSeqNo; // 0x08 - Log sequence number
+ UINT64 INDR_VCN; // 0x10 - Virtual Cluster Number
+ UINT32 INDR_IndxEntryOff; // 0x18 - Offset to Index Entries
+ // (from here, not from start)
+ UINT32 INDR_IndxEntrySize; // 0x1C - Size of Index Entries
+ UINT32 INDR_IndxEntryAlloc; // 0x20 - Allocated size of Entries
+ UINT8 INDR_LeafNode; // 0x24 - 1 if not leaf node
+ UINT8 INDR_Padding[3]; // 0x25 - Padding
+ UINT16 INDR_UpdateSequence; // 0x28 - Update Sequence
+ UINT16 INDR_SeqenceArray[1]; // 0x2A - Sequence Array
+} INDEX_RECORD;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: INDEX_ENTRY
+//
+// Description: Structure of an Index record entry.
+//
+// Referrals:
+//
+// Notes: In NTFS, the index is the equivalent of a directory in FAT,
+// so the index entry is the equivalent of a directory entry.
+// The lower 4 bytes of the MFT reference is the number of the
+// file's File Record in the MFT. The lower 4 bytes of the MFT
+// parent reference is the number of the File Record for the
+// Index that this entry is in.
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+typedef struct _INDEX_ENTRY
+{
+ UINT64 INDE_MFTRecord; // 0x00 - MFT reference of this entry's file
+ UINT16 INDE_EntrySize; // 0x08 - Size of this entry
+ UINT16 INDE_NameOffset; // 0x0a - Offset to file name
+ UINT16 INDE_IndexFlags; // 0x0C - Index Flags
+ UINT16 INDE_Padding;
+ UINT64 INDE_MFTParentRec; // 0x10 - MFT refernece of this entry's parent
+ UINT64 INDE_CreationTime; // 0x18 - File Creation Time
+ UINT64 INDE_AlteredTime; // 0x20 - File Altered Time
+ UINT64 INDE_MFTChangedTime; // 0x28 - MFT Record Changed Time
+ UINT64 INDE_ReadTime; // 0x30 - File Read Time
+ UINT64 INDE_AllocSize; // 0x38 - Allocated File Size
+ UINT64 INDE_RealSize; // 0x40 - Real File Size
+ UINT64 INDE_FileFlags; // 0x48 - File Flags (like DOS flags + more)
+ UINT8 INDE_NameLength; // 0x50 - Length of File name
+ UINT8 INDE_NameType; // 0x51 - File Name type
+ // 0x00 - POSIX
+ // 0x01 - Unicode
+ // 0x02 - DOS
+ // 0x03 - Both
+ CHAR16 INDE_Name[1]; // 0x52 - File Name (Unicode, not terminated)
+} INDEX_ENTRY;
+
+//
+// EXTx STRUCTURES
+//
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: DIR_ENTRY_EXT
+//
+// Description: Structure of a EXT directory entry
+//
+// Referrals:
+//
+// Notes: The directory entry length must be a multiple of 4 bytes
+// Padding will be added after the name if necessary.
+// Note that the directory does not contain any file info
+// other than the name. That info is in the inode for the file.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+typedef struct _DIR_ENTRY_EXT {
+ UINT32 DIR_Inode; // 0x00 - Inode no. of file
+ UINT16 DIR_EntryLength; // 0x04 - Length of dir. entry
+ UINT8 DIR_NameLength; // 0x06 - Length of name
+ UINT8 DIR_FileType; // 0x07 - Type of file
+ // 1 = regular file, 2 = directory
+ CHAR8 DIR_Name[1]; // 0x08 - File name starts here
+} DIR_ENTRY_EXT;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: VOLUME_SB
+//
+// Description: Structure of the Volume SuperBlock for EXT volumes.
+//
+// Referrals:
+//
+// Notes: The Superblock is equivalent to the BPB of a FAT or NTFS
+// volume, containing information about the volume. However,
+// it does not contain any boot code.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _VOLUME_SB {
+ UINT32 SB_TotalInodes; // 0x00 - Total Inodes
+ UINT32 SB_TotalBlocks; // 0x04 - Total size in blocks
+ UINT32 SB_ReservedBlocks; // 0x08 - Reserved blocks
+ UINT32 SB_FreeBlocks; // 0x0C - Free blocks
+ UINT32 SB_FreeInodes; // 0x10 - Free inodes
+ UINT32 SB_FirstBlock; // 0x14 - First data block (always 1 or 0)
+ UINT32 SB_BlockSize; // 0x18 - Block size shift value
+ // The actual block size is calculated
+ // as 1024 << SB_BlockSize
+ UINT32 SB_FragSize; // 0x0C - Fragment size
+ UINT32 SB_BlocksPerGroup; // 0x20 - Blocks per group
+ UINT32 SB_FragsPerGroup; // 0x24 - Fragments per group
+ UINT32 SB_InodesPerGroup; // 0x28 - Inodes per group
+ UINT32 SB_LastMountTime; // 0x2C - Time of last mount
+ UINT32 SB_LastWriteTime; // 0x30 - Time of last write
+ UINT16 SB_MountCount; // 0x34 - Count of mounts since verification
+ UINT16 SB_MaxMountCount; // 0x36 - Max mounts allowed before check
+ UINT16 SB_Magic; // 0x38 - Magic number (0xEF53)
+ UINT16 SB_StatusFlag; // 0x3A - 1 = clean, 2 = error
+ UINT16 SB_ErrorDo; // 0x3C - What to do if error
+ UINT16 SB_MinorRev; // 0x3E - Minor revision level
+ UINT32 SB_LastCheckTime; // 0x40
+ UINT32 SB_CheckInterval; // 0x44
+ UINT32 SB_CreatorOS; // 0x48 - OS that created the volume (0=Linux)
+ UINT32 SB_Revision; // 0x4C
+ UINT16 SB_DefaultUID; // 0x50 - Default User ID
+ UINT16 SB_DefaultGID; // 0x52 - Default Group ID
+ UINT32 SB_FirstInode; // 0x54 - First non-reserved inode
+ UINT16 SB_InodeStrucSize; // 0x58 - Inode structure size
+ UINT16 SB_BlockGroupNo; // 0x5A - Block Group Number
+ UINT32 SB_CompFeatMap; // 0x5C - Compatible feature bitmap
+ UINT32 SB_IncompFeatMap; // 0x60 - Incompatible feature bitmap
+ UINT32 SB_ROCompFeatMap; // 0x64 - Read-only comp. feature bitmap
+ EFI_GUID SB_UUID; // 0x68 - Volume Unique ID
+ CHAR8 SB_VolumeName[16]; // 0x78 - Volume name
+ CHAR8 SB_LastPath[64]; // 0x88 - Last mount path (normally not used)
+ UINT32 SB_AlgoBitmap; // 0xC8 - Compression algorithm bitmap
+ UINT8 SB_PreAllocBlocks; // 0xCC - Blocks to pre-allocate for new file
+ UINT8 SB_PreAllocBlocksDir;// 0xCD - Blocks to pre-allocate for new directory
+ UINT8 SB_Padding[512-0xCE];// 0xCE - Padding to 1024 starts here
+ // We're loading this into an MBR buffer,
+ // so we only pad to 512.
+} VOLUME_SB;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: VOLUME_BGDT
+//
+// Description: Structure of the Volume Block Group Descriptor Table.
+//
+// Referrals:
+//
+// Notes: In EXT, volumes are arranged as groups of blocks. The size
+// of each group is defined in SB_BlocksPerGroup in the
+// Superblock. The descriptor table gives info about the group.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _VOLUME_BGDT {
+ UINT32 BGDT_BlockBitmapBlk; // 0x00 - Block bitmap block number
+ UINT32 BGDT_InodeBitmapBlk; // 0x04 - Inode bitmap block number
+ UINT32 BGDT_InodeTableBlk; // 0x08 - Inode table block number
+ UINT16 BGDT_FreeBlocks; // 0x0C - Free blocks in the group
+ UINT16 BGDT_FreeInodes; // 0x0E - Free inodes in the group
+ UINT16 BGDT_UsedDirs; // 0x10 - Inodes used for directories in the group
+ UINT16 BGDT_Padding; // 0x12 - Padding
+ UINT8 BGDT_Reserved[12]; // 0x14 - Reserved
+} VOLUME_BGDT;
+
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: VOLUME_IT
+//
+// Description: Structure of an Inode table
+//
+// Referrals:
+//
+// Notes: The inode table table contains all the information about each
+// file EXCEPT the file's name, which is in the directory.
+// The directory contains the file's name and inode number.
+// The inodes are numbered sequentially in the table, and the
+// table occupies consecutive blocks.
+//
+// EXT2, EXT3 File allocation method:
+// The block map of the file in IT_Blocks works as follows:
+// The first 12 entries are direct block numbers of the file.
+// The 13th entry is the number of a block containing block
+// numbers of the file (single-indirect blocks).
+// The 14th entry is the number of a block containing block
+// numbers of blocks containing file block numbers (double-
+// indirect blocks).
+// Similarly, the 15th entry is triple-indirect blocks.
+// Therefore, the maximum file size with 1024-byte blocks
+// would be 12+256+65536+16777216 1024-byte blocks.
+//
+// EXT4 File allocation method:
+// Instead of a block map, EXT4 has a header followed by up
+// to 4 extents of contiguous blocks. If the entire file is
+// contiguous, there will be only one extent. Each extent
+// consists of a 32-bit logical block no. (relative to the
+// start of the file), a 16-bit block count, and a 48-bit
+// physical block number, expressed as a 16-bit high value
+// and a 32-bit low value. If a file requires more than 4
+// extents, the value of EH_Depth in the header will be
+// non-zero, and the first extent will point to a block of
+// extents indtead of the file.
+//
+// The file dates in VOLUME_IT are the number of seconds since
+// January 1, 1970.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _EXT_HDR {
+ UINT16 EH_Magic; // 0x00 - Magic number (0xF30A)
+ UINT16 EH_Extents; // 0x02 - Number of extents
+ UINT16 EH_Max; // 0x04 - Maximum no. of extents
+ UINT16 EH_Depth; // 0x06 - Depth of tree (0 normally)
+ UINT32 EH_Generation; // 0x08 - Generation ID (currently 0)
+} EXT_HDR;
+typedef struct _EXT_EXT {
+ UINT32 EE_LogBlk; // 0x00 - Logical block no.
+ UINT16 EE_Length; // 0x04 - Length of extent in blocks
+ UINT16 EE_BlockHi; // 0x06 - Uppper 16 bits of block no.
+ UINT32 EE_BlockLo; // 0x08 - Lower 32 bits of block no.
+} EXT_EXT;
+
+typedef struct _VOLUME_IT {
+ UINT16 IT_Type; // 0x00 - File type and access rights
+ // 0x8??? = regular file
+ // 0x4??? = directory
+ UINT16 IT_UID; // 0x02 - User ID
+ UINT32 IT_SizeLo; // 0x04 - File size (low 32 bits)
+ UINT32 IT_ATime; // 0x08 - Last access time
+ UINT32 IT_CTime; // 0x0C - File creation time
+ UINT32 IT_MTime; // 0x10 - File modified time
+ UINT32 IT_DTime; // 0x14 - File deleted time
+ UINT16 IT_GID; // 0x18 - Group ID
+ UINT16 IT_Links; // 0x1A - Links to this file (usually 1)
+ UINT32 IT_ListSize; // 0x1C - Block list size in 512-byte units.
+ UINT32 IT_Flags; // 0x20 - File flags
+ UINT32 IT_OSD1; // 0x24 - OS Dependant value no. 1
+ union
+ {
+ struct
+ {
+ UINT32 Blocks[15]; // 0x28 - Blocks occupied by file (see notes)
+ } Ext2;
+ struct
+ {
+ EXT_HDR Header; // 0x28 - Extent header
+ EXT_EXT Extent[4]; // 0x34 - Extents of file (see notes)
+ } Ext4;
+ } Alloc;
+ UINT32 IT_Version; // 0x64 - File version
+ UINT32 IT_FileACL; // 0x68 - File Access Control List
+ UINT32 IT_SizeHi; // 0x6C - File size (high 32 bits)
+ UINT32 IT_Fragment; // 0x70 - Not used in Linux
+ UINT32 IT_OSD2[3]; // 0x74 - OS Dependant value no. 2
+} VOLUME_IT;
+
+//<AMI_SHDR_START>
+//----------------------------------------------------------------------------
+// Name: MEMORY_BLOCK
+//
+// Description: Structure of a memory boock used to hold various basic
+// structures.
+//
+// Referrals:
+//
+// Notes: In order to make a smaller compiled binary, this memory block
+// is allocated, and used to hold structures that were formerly
+// reserved statically.
+//
+//----------------------------------------------------------------------------
+//<AMI_SHDR_END>
+
+typedef struct _MEMORY_BLOCK {
+ MASTER_BOOT_RECORD Mbr; // Master boot record (all file systems)
+ BOOT_SECTOR Bs; // Boot sector (FAT and NTFS)
+ UINT8 MFTRunList[256];// Master File Table run list (NTFS)
+ UINT8 RootRunList[128];// Root dir run list (NTFS)
+ UINT8 ResidentIndex[256];// Stores resident index (NTFS)
+ VOLUME_SB Sb; // Superblock (EXT(n))
+ VOLUME_IT RootInode; // Root directory inode (EXT(n))
+ VOLUME_IT FileInode; // File inode (EXT(n))
+} MEMORY_BLOCK;
+
+#pragma pack(pop)
+
+//**************** eLink override definitions *******************************
+//This functions may be overriden by eLinks
+
+VOID GetFileListFromPrimaryVolume(
+ IN DIR_RECORD *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_RECORD **Buffer
+);
+
+VOID GetFileListFromFatVolume(
+ IN DIR_ENTRY *Root,
+ IN UINT32 RootEntries,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY **Buffer
+);
+
+VOID GetFileListFromNtfsVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT INDEX_ENTRY **Buffer
+);
+
+VOID GetFileListFromExtVolume(
+ IN UINT8 *Root,
+ IN UINT32 RootSize,
+ OUT UINTN *NumberOfFiles,
+ OUT DIR_ENTRY_EXT **Buffer
+);
+
+BOOLEAN IsValidFile(
+ IN VOID *FileData,
+ IN UINTN FileSize
+);
+
+EFI_STATUS GetRecoveryFileInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT VOID **pCapsuleName,
+ IN OUT UINTN *pCapsuleSize,
+ OUT BOOLEAN *ExtendedVerification
+);
+
+/****** DO NOT WRITE BELOW THIS LINE *******/
+#ifdef __cplusplus
+}
+#endif
+#endif
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
diff --git a/Core/EM/Recovery/RecoverySrc.cif b/Core/EM/Recovery/RecoverySrc.cif
new file mode 100644
index 0000000..76a2a77
--- /dev/null
+++ b/Core/EM/Recovery/RecoverySrc.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "Recovery Sources"
+ category = ModulePart
+ LocalRoot = "Core\EM\Recovery\"
+ RefName = "RecoverySrc"
+[files]
+"RecoverySrc.sdl"
+"FsRecovery.c"
+"RecoverySrc.mak"
+"SerialRecovery.c"
+"IdeRecovery.c"
+"CapsuleRecovery.c"
+<endComponent>
diff --git a/Core/EM/Recovery/RecoverySrc.mak b/Core/EM/Recovery/RecoverySrc.mak
new file mode 100644
index 0000000..411502c
--- /dev/null
+++ b/Core/EM/Recovery/RecoverySrc.mak
@@ -0,0 +1,81 @@
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Core/Modules/Recovery/RecoverySrc.mak 8 6/16/11 9:02a Felixp $
+#
+# $Revision: 8 $
+#
+# $Date: 6/16/11 9:02a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Core/Modules/Recovery/RecoverySrc.mak $
+#
+# 8 6/16/11 9:02a Felixp
+# Enhancement: Replace NAME=RECOVERY with LIBRARY_NAME=$(RECOVERYLIB)
+# to avoid temporary files with identical names in Recovery and
+# RecoverySrc modules.
+#
+# 7 7/01/09 4:19p Rameshr
+# Coding Standard and File header updated.
+#
+# 6 12/29/06 2:59p Felixp
+#
+# 5 10/13/06 4:40p Felixp
+#
+# 4 8/24/06 9:33a Felixp
+# x64 Support: recovery.lib splitted into PEI and DXE parts
+#
+# 3 12/19/05 6:36p Felixp
+#
+# 2 12/02/05 11:22a Felixp
+#
+# 1 12/01/05 9:45a Felixp
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name: RecoverySrc.mak
+#
+# Description: Builds the Recovery source and create the Recovery.lib
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+all : RecoverySrc
+
+$(RECOVERYLIB) : RecoverySrc
+
+RecoverySrc : $(BUILD_DIR)\RecoverySrc.mak RecoverySrcPeiBin
+
+$(BUILD_DIR)\RecoverySrc.mak : $(Recovery_DIR)\$(@B).cif $(Recovery_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(Recovery_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+RecoverySrcPeiBin :
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\RecoverySrc.mak all\
+ MAKEFILE=$(BUILD_DIR)\RecoverySrc.mak\
+ LIBRARY_NAME=$(RECOVERYLIB) TYPE=PEI_LIBRARY
+
+#**********************************************************************
+#**********************************************************************
+#** **
+#** (C)Copyright 1985-2009, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Pkwy, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#**********************************************************************
+#**********************************************************************
diff --git a/Core/EM/Recovery/RecoverySrc.sdl b/Core/EM/Recovery/RecoverySrc.sdl
new file mode 100644
index 0000000..3c5513c
--- /dev/null
+++ b/Core/EM/Recovery/RecoverySrc.sdl
@@ -0,0 +1,21 @@
+TOKEN
+ Name = "RecoverySrc_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Recovery Sources support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Token = "Recovery_SUPPORT" "=" "1"
+End
+
+MODULE
+ File = "RecoverySrc.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\Recovery.lib"
+ Parent = "$(Recovery_DIR)\Recovery.lib"
+ InvokeOrder = ReplaceParent
+End
+
diff --git a/Core/EM/Recovery/SerialRecovery.c b/Core/EM/Recovery/SerialRecovery.c
new file mode 100644
index 0000000..1c59c62
--- /dev/null
+++ b/Core/EM/Recovery/SerialRecovery.c
@@ -0,0 +1,1047 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Core/Modules/Recovery/SerialRecovery.c 8 2/13/12 4:13a Rajeshms $
+//
+// $Revision: 8 $
+//
+// $Date: 2/13/12 4:13a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Core/Modules/Recovery/SerialRecovery.c $
+//
+// 8 2/13/12 4:13a Rajeshms
+// [TAG] EIP80704
+// [Category] New Feature
+// [Description] Serial Recovery support through PCI Serial Port .
+// [Files] PciSerialRecovery.mak, PciSerialRecovery.sdl,
+// PciSerialRecovery.c, PciSerialRecovery.h, PciSerialRecovery.chm,
+// PciSerialRecovery.dxs, SerialRecovery.c, SerialDevice.h
+//
+// 7 5/13/11 5:08p Artems
+// Added secure flash update support
+//
+// 6 11/25/09 4:53p Felixp
+// sAmiRomFile renamed to RecoveryFileName
+// FlashSize renamed ro RecoveryImageSize
+//
+// 5 7/10/09 10:42a Rameshr
+// Recovery from Multiple Serial Device support Added
+// EIP:21100
+//
+// 4 7/01/09 4:19p Rameshr
+// Coding Standard and File header updated.
+//
+// 3 5/20/06 2:58p Felixp
+//
+// 2 12/19/05 5:52p Robert
+// The GetSerialChar function was not returning the character properly in
+// the parameter list. A pointer was being created and it was initialized
+// to a value, but the pointer itself was never initialized. A CHAR8
+// variable was created and the pointer was initialized to that variable.
+// It worked in debug mode because the compiler set aside a data space for
+// the pointer and that the optimized version didn't.
+//
+// 1 12/01/05 9:45a Felixp
+//
+// 1 7/15/05 10:40a Eswark
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------
+//
+// Name: SerialRecovery.c - PEI driver
+//
+// Description: Implements Serial Recovery Functions
+//
+//----------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "Recovery.h"
+#include "RecoveryCsp.h"
+
+#include <AmiPeiLib.h>
+#include <Ppi\Stall.h>
+#include <Ppi\DeviceRecoveryModule.h>
+#include <Ppi\SerialDevice.h>
+
+
+#define BAUD_DIVISOR_LSB 0x0001
+#define BAUD_DIVISOR_MSB 0x0000
+#define MAX_USER_DELAY 0x1E84EC //wait for user response in 15 microseconds units
+#define MAX_DATA_DELAY 0x1046A //Wait for data byte in 50 microseconds units
+#define MAX_DATA1_DELAY 0x28B0A
+#define MAX_RESP_DELAY 0x1E //Max Response time in 1 second units
+#define XMODEM_SOH 0x01 // Start Header
+#define XMODEM_EOT 0x04 // End of Transfer
+#define XMODEM_ACK 0x06 // Acknowledge
+#define XMODEM_NAK 0x15 // Negative Acknowledge
+#define XMODEM_CAN 0x18 // Cancel Transfer
+
+#define COM_BASE_ADDRESS 0x3f8
+
+VOID SendSerialChar (
+ CHAR8 c
+);
+BOOLEAN GetSerialData1 (
+ UINT8* ReadData
+);
+BOOLEAN GetSerialData (
+ UINT8* ReadData
+);
+VOID SendSerialData (
+ UINT8 d
+);
+VOID SendSerialString (
+ CHAR8* Str
+);
+BOOLEAN GetSerialChar (
+ CHAR8* ReadChar
+);
+VOID PrintCopyRightMessage ( );
+VOID InitSerialPort ( );
+
+UINT8 ReadSerialDevice (
+ IN PEI_RECOVERY_SERIAL_MODE_PPI *This,
+ IN UINT8 Offset
+);
+
+VOID WriteSerialDevice (
+ IN PEI_RECOVERY_SERIAL_MODE_PPI *This,
+ IN UINT8 Offset,
+ IN UINT8 Data
+);
+
+EFI_PEI_SERVICES **mPeiServices;
+
+PEI_RECOVERY_SERIAL_MODE_PPI *SerialModePpi=NULL;
+
+EFI_STATUS
+EFIAPI GetNumberRecoveryCapsules (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ OUT UINTN *NumberRecoveryCapsules );
+
+EFI_STATUS
+EFIAPI GetRecoveryCapsuleInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT UINTN *Size,
+ OUT EFI_GUID *CapsuleType );
+
+EFI_STATUS
+EFIAPI LoadRecoveryCapsule (
+ IN OUT EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT VOID *Buffer );
+
+BOOLEAN ReadFileFromSerial (
+ CHAR8 * Buffer,
+ UINT32* Size,
+ UINT8 *result );
+
+BOOLEAN ReadSerialBlock (
+ UINT8* Buffer );
+
+BOOLEAN SendNakAck (
+ UINT8 * Data,
+ UINT8 XCommand );
+
+EFI_GUID gEfiPeiStallPpiGuid = EFI_PEI_STALL_PPI_GUID;
+static EFI_GUID gPeiDevRecModuleGuid = EFI_PEI_DEVICE_RECOVERY_MODULE_PPI_GUID;
+EFI_PEI_STALL_PPI *mStallPpi;
+
+EFI_PEI_DEVICE_RECOVERY_MODULE_PPI SerialRecoveryModule = {
+ GetNumberRecoveryCapsules, GetRecoveryCapsuleInfo, LoadRecoveryCapsule
+};
+
+// PPI to be installed
+EFI_PEI_PPI_DESCRIPTOR SerialRecoveryPpiList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidRecoveryDevice, &SerialRecoveryModule
+ }
+};
+
+EFI_GUID guidSerialRecoveryDevice=PEI_RECOVERY_SERIAL_MODE_PPI_GUID;
+
+PEI_RECOVERY_SERIAL_MODE_PPI ComSerialDevice =
+{
+ COM_BASE_ADDRESS,
+ ReadSerialDevice,
+ WriteSerialDevice
+};
+
+// PPI to be installed
+EFI_PEI_PPI_DESCRIPTOR SerialDevicePpiList[] =
+{
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &guidSerialRecoveryDevice, &ComSerialDevice
+ }
+};
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: SerialRecoveryPeimEntry
+//
+// Description: Serial Recovery PEI entry Function
+//
+// Input: IN EFI_FFS_FILE_HEADER *FfsHeader- FFSHeader
+// IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+EFIAPI SerialRecoveryPeimEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status;
+
+ mPeiServices = PeiServices;
+
+ Status = (*PeiServices)->LocatePpi(
+ PeiServices,
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ &mStallPpi
+ );
+ ASSERT_PEI_ERROR( PeiServices, Status );
+
+ Status = (*PeiServices)->InstallPpi( PeiServices, SerialRecoveryPpiList );
+
+ //
+ //Install the Serial Device for Com port 0x3f8
+ //
+ Status = (*PeiServices)->InstallPpi (PeiServices,SerialDevicePpiList);
+ ASSERT_PEI_ERROR( PeiServices, Status );
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetNumberRecoveryCapsules
+//
+// Description: Get the Number of Recovery Capsules
+//
+// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This
+// OUT UINTN *NumberRecoveryCapsules- Number of Recovery Capsule
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS
+EFIAPI GetNumberRecoveryCapsules(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ OUT UINTN *NumberRecoveryCapsules )
+{
+ *NumberRecoveryCapsules = 1;
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetRecoveryCapsuleInfo
+//
+// Description: Get the Recovery Capsule Information
+//
+// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This
+// IN UINTN CapsuleInstance,
+// OUT UINTN *Size,
+// OUT EFI_GUID *CapsuleType
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS
+EFIAPI GetRecoveryCapsuleInfo(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT UINTN *Size,
+ OUT EFI_GUID *CapsuleType )
+{
+ EFI_STATUS Status;
+
+ *CapsuleType = guidSerialCapsule;
+
+ Status = GetRecoveryFileInfo(PeiServices, NULL, Size, NULL);
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: PrintBaseAddress
+//
+// Description: Print the Serial Port base address
+//
+// Input: IN UINT16 BaseAddress
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PrintBaseAddress(
+ IN UINT64 BaseAddress
+)
+{
+
+ CHAR8 TempBuffer[5]={0,0,0,0,0};
+ UINTN ValueCharNum=0;
+ UINTN Remainder;
+ CHAR8 TempPrintBuffer[5]={0,0,0,0,0};
+ UINTN Index=0;
+
+ do {
+ BaseAddress = (UINT64)Div64 ((UINT64)BaseAddress, 0x10, &Remainder);
+
+ if(Remainder < 0xa) {
+ TempBuffer[ValueCharNum] = (CHAR8)(Remainder + '0');
+ } else {
+ TempBuffer[ValueCharNum] = (CHAR8)(Remainder + 'A' - 0xa);
+ }
+ ValueCharNum++;
+ } while (BaseAddress != 0);
+
+ //
+ // Reverse temp string into Buffer.
+ //
+ while (ValueCharNum) {
+ TempPrintBuffer[Index] = TempBuffer[ValueCharNum-1];
+ ValueCharNum--;
+ Index++;
+ }
+ SendSerialString(&TempPrintBuffer[0]);
+ return;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: LoadRecoveryCapsule
+//
+// Description: Download the Capsule file from the Serial device and returns the buffer
+//
+// Input: IN EFI_PEI_SERVICES **PeiServices - pointer to PEI services
+// IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This
+// IN UINTN CapsuleInstance,
+// OUT VOID *Buffer- Recovery Capsule Data
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+static EFI_STATUS
+EFIAPI LoadRecoveryCapsule(
+ IN OUT EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT VOID *Buffer )
+{
+ CHAR8 *pBuff;
+ UINT32 FileSize;
+ UINT8 Result = 0xFF;
+ CHAR8 *message;
+ UINTN Number;
+ CHAR8 Char = 0;
+ CHAR8 *ReadChar = &Char;
+ UINT32 waitCount;
+ BOOLEAN Recovery = FALSE;
+ UINT8 Index=0;
+ EFI_STATUS Status;
+ UINTN RecoveryCapsuleSize;
+ BOOLEAN ExtendedVerification;
+
+ Status = GetRecoveryFileInfo(PeiServices, NULL, &RecoveryCapsuleSize, &ExtendedVerification);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ mPeiServices = PeiServices;
+ Index=0;
+
+ do {
+
+ //
+ //Locate the Serial Device PPI
+ //
+ Status = (**PeiServices).LocatePpi (PeiServices, &guidSerialRecoveryDevice, Index, NULL, &SerialModePpi);
+
+ //
+ //If Found Proceed with Reading recovery file. If not break the loop and return the status
+ //
+ if ((EFI_ERROR (Status))) {
+ break;
+ }
+
+ FileSize = (UINT32)RecoveryCapsuleSize;
+
+ GetNumberRecoveryCapsules(PeiServices, This, &Number);
+ if(Number == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ InitSerialPort( );
+
+ *ReadChar = '\n';
+ SendSerialChar( *ReadChar );
+ PrintCopyRightMessage();
+
+ message="Press space to start recovery from Serial Address 0x";
+ //
+ //Display the Serial Port Base address
+ //
+ SendSerialString(message);
+ PrintBaseAddress((UINT64)SerialModePpi->SerialDeviceBaseAddress);
+ message="\n\r or 'N' to try Next Serial Device or 'Q' to quit\n\r";
+ SendSerialString(message);
+ do {
+ waitCount=0xF; // EKCheck
+ while ( waitCount-- ) {
+ if ( GetSerialChar( ReadChar ) == TRUE ) {
+ Recovery = TRUE;
+ break;
+ }
+ }
+
+ if(*ReadChar ==' ') {
+ break;
+ }
+
+ if (*ReadChar=='N' || *ReadChar=='n') {
+ //
+ // Try the Next Serial Device
+ //
+ message="Trying next serial device if avilable.\n\r";
+ SendSerialString(message);
+ Recovery=FALSE;
+ break;
+ }
+ if ( *ReadChar == 'Q' || *ReadChar == 'q' ) {
+ //
+ //Exit from Serial Recovery
+ //
+ message = "Serial Recovery is aborted by user.\n\r";
+ SendSerialString( message );
+ return EFI_ABORTED;
+ }
+ } while(Recovery==TRUE);
+
+ if(Recovery == FALSE) {
+ //
+ // Try Next Device
+ //
+ Index++;
+ continue;
+ }
+ message="Send BIOS image using XMODEM protocol\n\r";
+ SendSerialString( message );
+
+ //
+ //Wait for 3-5 Seconds before User Sends a file
+ //
+ mStallPpi->Stall( mPeiServices, mStallPpi, 20000000 );
+
+ pBuff = Buffer;
+
+ if ( !ReadFileFromSerial( pBuff, &FileSize, &Result )) {
+ PEI_TRACE((-1, PeiServices, "\nRead File Failed Capsule Size= %d, FileRead Result=%d\n", FileSize, Result));
+
+ if ( Result == 1 ) {
+ PEI_TRACE((-1, PeiServices, "\nNo Responce from Terminal\n"));
+ }
+
+ if ( Result == 3 ) {
+ PEI_TRACE((-1, PeiServices, "\nFile Size over Run\n"));
+ }
+
+ //
+ // Error getting Recovery file from current serial device. So try another
+ // Serial Device
+ //
+ Index++;
+ continue;
+ } else {
+ //
+ //File got successfully. So Return
+ //
+ if(ExtendedVerification || FileSize == (UINT32)RecoveryCapsuleSize)
+ return EFI_SUCCESS;
+ }
+ }while(TRUE);
+
+ return EFI_NOT_FOUND;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: InitSerialPort
+//
+// Description: Initilize the Serial port Registers
+//
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID InitSerialPort( )
+{
+ //
+ // Disable all interrupts
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, InteruptEnableReg, 0x00);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Enable Baud Rate Programming
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, LineControlReg, 0x80);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Program Baud Rate LSB
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, SerialDataReg, BAUD_DIVISOR_LSB);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Program Baud Rate MSB
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, InteruptEnableReg, BAUD_DIVISOR_MSB);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Set to 8 bits, 1 Stop, No Parity
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, LineControlReg, 0x03);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Clear and enable FIFOs
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, FifoControlReg, 0x01);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Disable all interrupts
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, InteruptEnableReg, 0x00);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Clear and enable FIFOs
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, FifoControlReg, 0xC7);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+ //
+ // Activate DTR and RTS
+ //
+ SerialModePpi->WriteSerialDevice(SerialModePpi, ModemControlReg, 0x03);
+ mStallPpi->Stall( mPeiServices, mStallPpi, 1000 );
+
+ //
+ // Discard any garbage that may be in the receive FIFO
+ //
+ while ( (SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg)) & 01 ) {
+ SerialModePpi->ReadSerialDevice(SerialModePpi,SerialDataReg); // else, read data and discard
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadFileFromSerial
+//
+// Description: Read the Recovery file through Serial Device
+//
+// Input: CHAR8 * Buffer- Data buffer
+// UINT32* Size- Size
+// UINT8 * result- Result Status
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN ReadFileFromSerial(
+ CHAR8 * Buffer,
+ UINT32* Size,
+ UINT8 * result )
+{
+ // Read recovery file through serial port, check checksum, signature etc.,
+ // and copy it to the buffer ImageStart.
+
+ UINT32 NumBlocks = *Size / 128;
+ UINT32 count = 10;
+ UINT32 BlockID = 1;
+ UINT32 TimeOut = 10; //1 second (in .1 sec units) timeout
+ UINT8 BlockNum = 1;
+ UINT8 Command = XMODEM_NAK;
+ UINT8 Data = 0;
+ CHAR8* InChar = '\0';
+ BOOLEAN Status;
+
+ NumBlocks++;
+ while ( NumBlocks )
+ {
+ if ( !SendNakAck( &Data, Command )) //send NAK
+ {
+ *result = 1;
+ return FALSE;
+ }
+
+ if ( Data == XMODEM_EOT ) //if end of transfer, exit with success
+ {
+ Command = XMODEM_ACK;
+ SendSerialData( Command );
+ BlockID--;
+ *Size = BlockID * 128;
+ *result = 0;
+ return TRUE;
+ }
+
+ if ( Data == XMODEM_SOH ) {
+ //
+ //Start header received, get rest of the packet
+ //
+ Status = GetSerialData( &Data );
+ //
+ //read block#
+ //
+ if ( Status && (Data == BlockNum)) {
+ Status = GetSerialData( &Data );
+
+ if ( Status ) {
+ //if FF-block number doesn't match, retry
+ if ( ReadSerialBlock( Buffer )) {
+ // Read 128 byte packet
+ BlockNum++;
+ BlockID++;
+ NumBlocks--;
+ Command = XMODEM_ACK;
+ continue;
+ }
+ }
+ }
+ while ( GetSerialData( &Data ))
+ {
+ ;
+ }
+ }
+ }
+
+ //
+ //No more block to read, No EOT byte received, terminate xfer and exit with error
+ //
+ *result = 3;
+ while ( GetSerialData( &Data )) {
+ ; //If abort, read and discard
+ }
+ Command = XMODEM_CAN;
+ while ( count-- ) {
+ SendSerialData( Command ); // Send CANCEL Command
+ }
+ return FALSE;
+}
+
+UINT32 CurrentIndex = 0; //global variable to hold current buffer index
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: ReadSerialBlock
+//
+// Description: Read the Serial Block
+//
+// Input: CHAR8 * Buffer- Data buffer
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN ReadSerialBlock(
+ UINT8* Buffer )
+{
+ UINT8 CheckSum = 0;
+ UINT8 DataByte = 0;
+ UINT8 * DataBuffer = Buffer;
+ UINT32 TempIndex = CurrentIndex;
+ UINT8 bytecount;
+
+ //
+ //read 128 byte packet
+ //
+ for ( bytecount = 1; bytecount <= 128; bytecount++ ) {
+ //
+ //if error reading serial port, retry packet
+ //
+ if ( !(GetSerialData( DataBuffer + CurrentIndex ))) {
+ CurrentIndex = TempIndex;
+ return FALSE;
+ }
+ CheckSum += *(DataBuffer + CurrentIndex++);
+ }
+
+ //
+ //Get Checksum byte
+ //
+ if ( !(GetSerialData( &DataByte ))) {
+ CurrentIndex = TempIndex;
+ return FALSE;
+ }
+
+ //
+ //if byte checksum doesn't match, retry
+ //
+ if ( DataByte != CheckSum ) {
+ CurrentIndex = TempIndex;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: SendNakAck
+//
+// Description: Send the Ack
+//
+// Input: UINT8 * Data,
+// UINT8 XCommand
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN SendNakAck(
+ UINT8 * Data,
+ UINT8 XCommand )
+{
+ UINT8 AbortCount = 12, count = 24; //Number of NAKs or ACKs to send before abort
+ CHAR8 * SerialMsg;
+
+ while ( count-- ){
+ SendSerialData( XCommand );
+
+ if ( GetSerialData1( Data )) {
+ return TRUE;
+ }
+ }
+ //if timeout, cancel the transfer and
+ // return false, with abort message
+ while ( GetSerialData( Data )) //If abort, read and discard
+ {
+ ;
+ }
+ XCommand = XMODEM_CAN;
+ while ( AbortCount-- ) {
+ SendSerialData( XCommand ); // Send CANCEL Command
+ }
+ SerialMsg = "\n\rAborting Serial Recovery";
+ SendSerialString( SerialMsg );
+ return FALSE;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: SendSerialChar
+//
+// Description: Send a character to Serial Port
+//
+// Input: CHAR8 c- Data to send
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SendSerialChar(
+ CHAR8 c )
+{
+ while ( !(SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x20) ) {
+ ;
+ }
+ SerialModePpi->WriteSerialDevice(SerialModePpi, SerialDataReg, (UINT8)c);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetSerialData1
+//
+// Description: Get the Data from Serial Port
+//
+// Input: UINT8* ReadData - Data Got from Serial Device
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GetSerialData1(
+ UINT8* ReadData )
+{
+ long MaxDelay = MAX_DATA1_DELAY;
+
+ //
+ // wait for upto 1 second for the data byte to be ready
+ //
+ while ( MaxDelay-- )
+ {
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x0A ) {
+ //
+ //exit if overrun/framing error
+ //
+ return FALSE;
+ }
+
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x01 ) {
+ //
+ //exit loop if character ready in Reveive buffer
+ //
+ break;
+ }
+ }
+
+ if ( MaxDelay <= 0 ) {
+ return FALSE;
+ }
+
+ //
+ //read data byte from receive biffer
+ //
+ *ReadData = SerialModePpi->ReadSerialDevice(SerialModePpi,SerialDataReg);
+
+ return TRUE;
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetSerialData
+//
+// Description: Get the Data from Serial Port
+//
+// Input: UINT8* ReadData - Data Got from Serial Device
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GetSerialData(
+ UINT8* ReadData )
+{
+ long MaxDelay = MAX_DATA_DELAY;
+ volatile infinite = 1;
+ //
+ //wait for upto 1 second for the data byte to be ready
+ //
+ while ( MaxDelay-- )
+ {
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x0A ) {
+ //
+ //exit if overrun/framing error
+ //
+ return FALSE;
+ }
+
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x01 ) {
+ //
+ //exit loop if character ready in Reveive buffer
+ //
+ break;
+ }
+ }
+
+ if ( MaxDelay <= 0 ) {
+ return FALSE;
+ }
+ //
+ //read data byte from receive biffer
+ //
+ *ReadData = SerialModePpi->ReadSerialDevice(SerialModePpi,SerialDataReg);
+
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: SendSerialData
+//
+// Description: Send the Data to serial Device
+//
+// Input: UINT8 d - Data to be send it to Serial Device
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SendSerialData(
+ UINT8 d )
+{
+ while ( !(SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x20) )
+ {
+ ;
+ }
+ SerialModePpi->WriteSerialDevice(SerialModePpi, SerialDataReg, d);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: SendSerialString
+//
+// Description: Send the String to serial Device
+//
+// Input: CHAR8* Str - String to be send it to Serial Device
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SendSerialString(
+ CHAR8* Str )
+{
+ while ( *Str )
+ {
+ SendSerialChar( *Str++ );
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: GetSerialChar
+//
+// Description: Get the Char from the Serial Device
+//
+// Input: CHAR8* ReadChar - Data from Serial Device
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN GetSerialChar(
+ CHAR8* ReadChar ) // ReadChar is the output character
+{
+ long MaxDelay = MAX_USER_DELAY;
+
+ //
+ //Wait for upto 30s for the user to enter Response
+ //
+ while ( MaxDelay-- ) {
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x0A ) {
+ //
+ //exit if overrun/framing error
+ //
+ return FALSE;
+ }
+
+ if ( SerialModePpi->ReadSerialDevice(SerialModePpi,LineStatusReg) & 0x01 ) {
+ //
+ //exit loop if character ready in Reveive buffer
+ //
+ break;
+ }
+ }
+
+ if ( MaxDelay <= 0 ) {
+ return FALSE;
+ }
+ //
+ //read character from receive biffer
+ //
+ *ReadChar = (CHAR8) SerialModePpi->ReadSerialDevice(SerialModePpi,SerialDataReg);
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------
+//
+// Procedure: PrintCopyRightMessage
+//
+// Description: Display the CopyRight Message in Serial Device
+//
+//
+//----------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID PrintCopyRightMessage( )
+{
+ static CHAR8
+ *Message = "\n\r*********************************************************\n\r"
+ "(C)Copyright 1985-2012, American Megatrends, Inc.\n\r"
+ " All Rights Reserved.\n\r"
+ " AMI Serial Recovery.\n\r"
+ "*********************************************************\n\r";
+
+ SendSerialString( Message );
+}
+
+// <AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: ReadSerialDevice
+//
+// Description:
+// Reads from address(COM_BASE_ADDRESS+offset) that is mapped toSerial
+// Device.
+//
+// Input:
+// IN PEI_RECOVERY_SERIAL_MODE_PPI *This - Pointer to
+// PEI_RECOVERY_SERIAL_MODE_PPI
+// IN UINT8 Offset - Offset to read the data from the Baseaddress
+//
+// Output:
+// UINT8 - Data Read from the Device
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//---------------------------------------------------------------------------
+// <AMI_PHDR_END>
+UINT8 ReadSerialDevice (
+ IN PEI_RECOVERY_SERIAL_MODE_PPI *This,
+ IN UINT8 Offset
+)
+{
+ return IoRead8( COM_BASE_ADDRESS + Offset );
+}
+
+// <AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Name: WriteSerialDevice
+//
+// Description:
+// Writes into address(COM_BASE_ADDRESS+offset) that is mapped to Serial
+// Device.
+//
+// Input:
+// IN PEI_RECOVERY_SERIAL_MODE_PPI *This - Pointer to
+// PEI_RECOVERY_SERIAL_MODE_PPI
+// IN UINT8 Offset - Offset to write the data from the Baseaddress
+// IN UINT8 Data - Data to be written
+//
+// Output:
+// VOID
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//---------------------------------------------------------------------------
+// <AMI_PHDR_END>
+VOID WriteSerialDevice (
+ IN PEI_RECOVERY_SERIAL_MODE_PPI *This,
+ IN UINT8 Offset,
+ IN UINT8 Data
+)
+{
+ IoWrite8( COM_BASE_ADDRESS + Offset , Data );
+}
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2009, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************