mirror of https://github.com/acidanthera/audk.git
FatPkg: Add FAT PEIM
Signed-off-by: jljusten Reviewed-by: mdkinney (based on FatPkg commit bead7f219277e063ed28589de8ddd01cf180c1a8) [jordan.l.justen@intel.com: Use script to relicense to 2-clause BSD] Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jordan Justen <jordan.l.justen@intel.com> Acked-by: Mark Doran <mark.doran@intel.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
43ba790742
commit
2f4dfa84ac
|
@ -0,0 +1,527 @@
|
||||||
|
/** @file
|
||||||
|
FAT file system access routines for FAT recovery PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FatLitePeim.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if there is a valid FAT in the corresponding Block device
|
||||||
|
of the volume and if yes, fill in the relevant fields for the
|
||||||
|
volume structure. Note there should be a valid Block device number
|
||||||
|
already set.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global
|
||||||
|
variables.
|
||||||
|
@param Volume On input, the BlockDeviceNumber field of the
|
||||||
|
Volume should be a valid value. On successful
|
||||||
|
output, all fields except the VolumeNumber
|
||||||
|
field is initialized.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS A FAT is found and the volume structure is
|
||||||
|
initialized.
|
||||||
|
@retval EFI_NOT_FOUND There is no FAT on the corresponding device.
|
||||||
|
@retval EFI_DEVICE_ERROR There is something error while accessing device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetBpbInfo (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN OUT PEI_FAT_VOLUME *Volume
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_BOOT_SECTOR Bpb;
|
||||||
|
PEI_FAT_BOOT_SECTOR_EX BpbEx;
|
||||||
|
UINT32 Sectors;
|
||||||
|
UINT32 SectorsPerFat;
|
||||||
|
UINT32 RootDirSectors;
|
||||||
|
UINT64 FatLba;
|
||||||
|
UINT64 RootLba;
|
||||||
|
UINT64 FirstClusterLba;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read in the BPB
|
||||||
|
//
|
||||||
|
Status = FatReadDisk (
|
||||||
|
PrivateData,
|
||||||
|
Volume->BlockDeviceNo,
|
||||||
|
0,
|
||||||
|
sizeof (PEI_FAT_BOOT_SECTOR_EX),
|
||||||
|
&BpbEx
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem (
|
||||||
|
(UINT8 *) (&Bpb),
|
||||||
|
(UINT8 *) (&BpbEx),
|
||||||
|
sizeof (PEI_FAT_BOOT_SECTOR)
|
||||||
|
);
|
||||||
|
|
||||||
|
Volume->FatType = FatUnknown;
|
||||||
|
|
||||||
|
Sectors = Bpb.Sectors;
|
||||||
|
if (Sectors == 0) {
|
||||||
|
Sectors = Bpb.LargeSectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
SectorsPerFat = Bpb.SectorsPerFat;
|
||||||
|
if (SectorsPerFat == 0) {
|
||||||
|
SectorsPerFat = BpbEx.LargeSectorsPerFat;
|
||||||
|
Volume->FatType = Fat32;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Filter out those not a FAT
|
||||||
|
//
|
||||||
|
if (Bpb.Ia32Jump[0] != 0xe9 && Bpb.Ia32Jump[0] != 0xeb && Bpb.Ia32Jump[0] != 0x49) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bpb.ReservedSectors == 0 || Bpb.NoFats == 0 || Sectors == 0) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bpb.SectorsPerCluster != 1 &&
|
||||||
|
Bpb.SectorsPerCluster != 2 &&
|
||||||
|
Bpb.SectorsPerCluster != 4 &&
|
||||||
|
Bpb.SectorsPerCluster != 8 &&
|
||||||
|
Bpb.SectorsPerCluster != 16 &&
|
||||||
|
Bpb.SectorsPerCluster != 32 &&
|
||||||
|
Bpb.SectorsPerCluster != 64 &&
|
||||||
|
Bpb.SectorsPerCluster != 128
|
||||||
|
) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Volume->FatType == Fat32 && (SectorsPerFat == 0 || BpbEx.FsVersion != 0)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Bpb.Media != 0xf0 &&
|
||||||
|
Bpb.Media != 0xf8 &&
|
||||||
|
Bpb.Media != 0xf9 &&
|
||||||
|
Bpb.Media != 0xfb &&
|
||||||
|
Bpb.Media != 0xfc &&
|
||||||
|
Bpb.Media != 0xfd &&
|
||||||
|
Bpb.Media != 0xfe &&
|
||||||
|
Bpb.Media != 0xff &&
|
||||||
|
//
|
||||||
|
// FujitsuFMR
|
||||||
|
//
|
||||||
|
Bpb.Media != 0x00 &&
|
||||||
|
Bpb.Media != 0x01 &&
|
||||||
|
Bpb.Media != 0xfa
|
||||||
|
) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Volume->FatType != Fat32 && Bpb.RootEntries == 0) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If this is fat32, refuse to mount mirror-disabled volumes
|
||||||
|
//
|
||||||
|
if (Volume->FatType == Fat32 && ((BpbEx.ExtendedFlags & 0x80) != 0)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Fill in the volume structure fields
|
||||||
|
// (Sectors & SectorsPerFat is computed earlier already)
|
||||||
|
//
|
||||||
|
Volume->ClusterSize = Bpb.SectorSize * Bpb.SectorsPerCluster;
|
||||||
|
Volume->RootEntries = Bpb.RootEntries;
|
||||||
|
Volume->SectorSize = Bpb.SectorSize;
|
||||||
|
|
||||||
|
RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (Volume->SectorSize - 1)) / Volume->SectorSize;
|
||||||
|
|
||||||
|
FatLba = Bpb.ReservedSectors;
|
||||||
|
RootLba = Bpb.NoFats * SectorsPerFat + FatLba;
|
||||||
|
FirstClusterLba = RootLba + RootDirSectors;
|
||||||
|
|
||||||
|
Volume->VolumeSize = MultU64x32 (Sectors, Volume->SectorSize);
|
||||||
|
Volume->FatPos = MultU64x32 (FatLba, Volume->SectorSize);
|
||||||
|
Volume->RootDirPos = MultU64x32 (RootLba, Volume->SectorSize);
|
||||||
|
Volume->FirstClusterPos = MultU64x32 (FirstClusterLba, Volume->SectorSize);
|
||||||
|
Volume->MaxCluster = (UINT32) (Sectors - FirstClusterLba) / Bpb.SectorsPerCluster;
|
||||||
|
Volume->RootDirCluster = BpbEx.RootDirFirstCluster;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this is not a fat32, determine if it's a fat16 or fat12
|
||||||
|
//
|
||||||
|
if (Volume->FatType != Fat32) {
|
||||||
|
|
||||||
|
if (Volume->MaxCluster >= 65525) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume->FatType = Volume->MaxCluster < 4085 ? Fat12 : Fat16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the next cluster in the cluster chain
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param Volume The volume
|
||||||
|
@param Cluster The cluster
|
||||||
|
@param NextCluster The cluster number of the next cluster
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The address is got
|
||||||
|
@retval EFI_INVALID_PARAMETER ClusterNo exceeds the MaxCluster of the volume.
|
||||||
|
@retval EFI_DEVICE_ERROR Read disk error
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetNextCluster (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_VOLUME *Volume,
|
||||||
|
IN UINT32 Cluster,
|
||||||
|
OUT UINT32 *NextCluster
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT64 FatEntryPos;
|
||||||
|
UINT32 Dummy;
|
||||||
|
|
||||||
|
*NextCluster = 0;
|
||||||
|
|
||||||
|
if (Volume->FatType == Fat32) {
|
||||||
|
FatEntryPos = Volume->FatPos + MultU64x32 (4, Cluster);
|
||||||
|
|
||||||
|
Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 4, NextCluster);
|
||||||
|
*NextCluster &= 0x0fffffff;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pad high bits for our FAT_CLUSTER_... macro definitions to work
|
||||||
|
//
|
||||||
|
if ((*NextCluster) >= 0x0ffffff7) {
|
||||||
|
*NextCluster |= (-1 &~0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (Volume->FatType == Fat16) {
|
||||||
|
FatEntryPos = Volume->FatPos + MultU64x32 (2, Cluster);
|
||||||
|
|
||||||
|
Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pad high bits for our FAT_CLUSTER_... macro definitions to work
|
||||||
|
//
|
||||||
|
if ((*NextCluster) >= 0xfff7) {
|
||||||
|
*NextCluster |= (-1 &~0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
FatEntryPos = Volume->FatPos + DivU64x32Remainder (MultU64x32 (3, Cluster), 2, &Dummy);
|
||||||
|
|
||||||
|
Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
|
||||||
|
|
||||||
|
if ((Cluster & 0x01) != 0) {
|
||||||
|
*NextCluster = (*NextCluster) >> 4;
|
||||||
|
} else {
|
||||||
|
*NextCluster = (*NextCluster) & 0x0fff;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Pad high bits for our FAT_CLUSTER_... macro definitions to work
|
||||||
|
//
|
||||||
|
if ((*NextCluster) >= 0x0ff7) {
|
||||||
|
*NextCluster |= (-1 &~0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set a file's CurrentPos and CurrentCluster, then compute StraightReadAmount.
|
||||||
|
|
||||||
|
@param PrivateData the global memory map
|
||||||
|
@param File the file
|
||||||
|
@param Pos the Position which is offset from the file's
|
||||||
|
CurrentPos
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Success.
|
||||||
|
@retval EFI_INVALID_PARAMETER Pos is beyond file's size.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetFilePos (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *File,
|
||||||
|
IN UINT32 Pos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 AlignedPos;
|
||||||
|
UINT32 Offset;
|
||||||
|
UINT32 Cluster;
|
||||||
|
UINT32 PrevCluster;
|
||||||
|
|
||||||
|
if (File->IsFixedRootDir) {
|
||||||
|
|
||||||
|
if (Pos >= MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
File->CurrentPos += Pos;
|
||||||
|
File->StraightReadAmount = (UINT32) (MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
|
||||||
|
AlignedPos = (UINT32) File->CurrentPos - (UINT32) Offset;
|
||||||
|
|
||||||
|
while
|
||||||
|
(
|
||||||
|
!FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster) &&
|
||||||
|
AlignedPos + File->Volume->ClusterSize <= File->CurrentPos + Pos
|
||||||
|
) {
|
||||||
|
AlignedPos += File->Volume->ClusterSize;
|
||||||
|
Status = FatGetNextCluster (
|
||||||
|
PrivateData,
|
||||||
|
File->Volume,
|
||||||
|
File->CurrentCluster,
|
||||||
|
&File->CurrentCluster
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
File->CurrentPos += Pos;
|
||||||
|
|
||||||
|
File->StraightReadAmount = 0;
|
||||||
|
Cluster = File->CurrentCluster;
|
||||||
|
while (!FAT_CLUSTER_FUNCTIONAL (Cluster)) {
|
||||||
|
File->StraightReadAmount += File->Volume->ClusterSize;
|
||||||
|
PrevCluster = Cluster;
|
||||||
|
Status = FatGetNextCluster (PrivateData, File->Volume, Cluster, &Cluster);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cluster != PrevCluster + 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
|
||||||
|
File->StraightReadAmount -= (UINT32) Offset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads file data. Updates the file's CurrentPos.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param File The file.
|
||||||
|
@param Size The amount of data to read.
|
||||||
|
@param Buffer The buffer storing the data.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data is read.
|
||||||
|
@retval EFI_INVALID_PARAMETER File is invalid.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadFile (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *File,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
CHAR8 *BufferPtr;
|
||||||
|
UINT32 Offset;
|
||||||
|
UINT64 PhysicalAddr;
|
||||||
|
UINTN Amount;
|
||||||
|
|
||||||
|
BufferPtr = Buffer;
|
||||||
|
|
||||||
|
if (File->IsFixedRootDir) {
|
||||||
|
//
|
||||||
|
// This is the fixed root dir in FAT12 and FAT16
|
||||||
|
//
|
||||||
|
if (File->CurrentPos + Size > File->Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatReadDisk (
|
||||||
|
PrivateData,
|
||||||
|
File->Volume->BlockDeviceNo,
|
||||||
|
File->Volume->RootDirPos + File->CurrentPos,
|
||||||
|
Size,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
File->CurrentPos += (UINT32) Size;
|
||||||
|
return Status;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ((File->Attributes & FAT_ATTR_DIRECTORY) == 0) {
|
||||||
|
Size = Size < (File->FileSize - File->CurrentPos) ? Size : (UINTN) (File->FileSize - File->CurrentPos);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// This is a normal cluster based file
|
||||||
|
//
|
||||||
|
while (Size != 0) {
|
||||||
|
DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
|
||||||
|
PhysicalAddr = File->Volume->FirstClusterPos + MultU64x32 (File->Volume->ClusterSize, File->CurrentCluster - 2);
|
||||||
|
|
||||||
|
Amount = File->StraightReadAmount;
|
||||||
|
Amount = Size > Amount ? Amount : Size;
|
||||||
|
Status = FatReadDisk (
|
||||||
|
PrivateData,
|
||||||
|
File->Volume->BlockDeviceNo,
|
||||||
|
PhysicalAddr + Offset,
|
||||||
|
Amount,
|
||||||
|
BufferPtr
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Advance the file's current pos and current cluster
|
||||||
|
//
|
||||||
|
FatSetFilePos (PrivateData, File, (UINT32) Amount);
|
||||||
|
|
||||||
|
BufferPtr += Amount;
|
||||||
|
Size -= Amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function reads the next item in the parent directory and
|
||||||
|
initializes the output parameter SubFile (CurrentPos is initialized to 0).
|
||||||
|
The function updates the CurrentPos of the parent dir to after the item read.
|
||||||
|
If no more items were found, the function returns EFI_NOT_FOUND.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param ParentDir The parent directory.
|
||||||
|
@param SubFile The File structure containing the sub file that
|
||||||
|
is caught.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The next sub file is obtained.
|
||||||
|
@retval EFI_INVALID_PARAMETER The ParentDir is not a directory.
|
||||||
|
@retval EFI_NOT_FOUND No more sub file exists.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadNextDirectoryEntry (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *ParentDir,
|
||||||
|
OUT PEI_FAT_FILE *SubFile
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
FAT_DIRECTORY_ENTRY DirEntry;
|
||||||
|
CHAR16 *Pos;
|
||||||
|
CHAR16 BaseName[9];
|
||||||
|
CHAR16 Ext[4];
|
||||||
|
|
||||||
|
ZeroMem ((UINT8 *) SubFile, sizeof (PEI_FAT_FILE));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pick a valid directory entry
|
||||||
|
//
|
||||||
|
while (1) {
|
||||||
|
//
|
||||||
|
// Read one entry
|
||||||
|
//
|
||||||
|
Status = FatReadFile (PrivateData, ParentDir, 32, &DirEntry);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We only search for *FILE* in root directory
|
||||||
|
// Long file name entry is *NOT* supported
|
||||||
|
//
|
||||||
|
if ((DirEntry.Attributes == FAT_ATTR_DIRECTORY) || (DirEntry.Attributes == FAT_ATTR_LFN)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// if this is a terminator dir entry, just return EFI_NOT_FOUND
|
||||||
|
//
|
||||||
|
if (DirEntry.FileName[0] == EMPTY_ENTRY_MARK) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If this not an invalid entry neither an empty entry, this is what we want.
|
||||||
|
// otherwise we will start a new loop to continue to find something meaningful
|
||||||
|
//
|
||||||
|
if ((UINT8) DirEntry.FileName[0] != DELETE_ENTRY_MARK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// fill in the output parameter
|
||||||
|
//
|
||||||
|
EngFatToStr (8, DirEntry.FileName, BaseName);
|
||||||
|
EngFatToStr (3, DirEntry.FileName + 8, Ext);
|
||||||
|
|
||||||
|
Pos = (UINT16 *) SubFile->FileName;
|
||||||
|
SetMem ((UINT8 *) Pos, FAT_MAX_FILE_NAME_LENGTH, 0);
|
||||||
|
CopyMem ((UINT8 *) Pos, (UINT8 *) BaseName, 2 * (StrLen (BaseName) + 1));
|
||||||
|
|
||||||
|
if (Ext[0] != 0) {
|
||||||
|
Pos += StrLen (BaseName);
|
||||||
|
*Pos = '.';
|
||||||
|
Pos++;
|
||||||
|
CopyMem ((UINT8 *) Pos, (UINT8 *) Ext, 2 * (StrLen (Ext) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SubFile->Attributes = DirEntry.Attributes;
|
||||||
|
SubFile->CurrentCluster = DirEntry.FileCluster;
|
||||||
|
if (ParentDir->Volume->FatType == Fat32) {
|
||||||
|
SubFile->CurrentCluster |= DirEntry.FileClusterHigh << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubFile->CurrentPos = 0;
|
||||||
|
SubFile->FileSize = DirEntry.FileSize;
|
||||||
|
SubFile->StartingCluster = SubFile->CurrentCluster;
|
||||||
|
SubFile->Volume = ParentDir->Volume;
|
||||||
|
|
||||||
|
if (SubFile->StartingCluster != 0) {
|
||||||
|
Status = FatSetFilePos (PrivateData, SubFile, 0);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// in Pei phase, time parameters do not need to be filled for minimum use.
|
||||||
|
//
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -0,0 +1,611 @@
|
||||||
|
/** @file
|
||||||
|
FAT recovery PEIM entry point, Ppi Functions and FAT Api functions.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FatLitePeim.h"
|
||||||
|
|
||||||
|
PEI_FAT_PRIVATE_DATA *mPrivateData = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
BlockIo installation nofication function. Find out all the current BlockIO
|
||||||
|
PPIs in the system and add them into private data. Assume there is
|
||||||
|
|
||||||
|
@param PeiServices General purpose services available to every
|
||||||
|
PEIM.
|
||||||
|
@param NotifyDescriptor The typedef structure of the notification
|
||||||
|
descriptor. Not used in this function.
|
||||||
|
@param Ppi The typedef structure of the PPI descriptor.
|
||||||
|
Not used in this function.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
BlockIoNotifyEntry (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
||||||
|
IN VOID *Ppi
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Discover all the block I/O devices to find the FAT volume.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global
|
||||||
|
variables.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UpdateBlocksAndVolumes (
|
||||||
|
IN OUT PEI_FAT_PRIVATE_DATA *PrivateData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
|
||||||
|
UINTN BlockIoPpiInstance;
|
||||||
|
EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;
|
||||||
|
UINTN NumberBlockDevices;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_PEI_BLOCK_IO_MEDIA Media;
|
||||||
|
PEI_FAT_VOLUME Volume;
|
||||||
|
EFI_PEI_SERVICES **PeiServices;
|
||||||
|
|
||||||
|
PeiServices = (EFI_PEI_SERVICES **) GetPeiServicesTablePointer ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clean up caches
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
|
||||||
|
PrivateData->CacheBuffer[Index].Valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateData->BlockDeviceCount = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find out all Block Io Ppi instances within the system
|
||||||
|
// Assuming all device Block Io Peims are dispatched already
|
||||||
|
//
|
||||||
|
for (BlockIoPpiInstance = 0; BlockIoPpiInstance < PEI_FAT_MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {
|
||||||
|
Status = PeiServicesLocatePpi (
|
||||||
|
&gEfiPeiVirtualBlockIoPpiGuid,
|
||||||
|
BlockIoPpiInstance,
|
||||||
|
&TempPpiDescriptor,
|
||||||
|
(VOID **) &BlockIoPpi
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Done with all Block Io Ppis
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = BlockIoPpi->GetNumberOfBlockDevices (
|
||||||
|
PeiServices,
|
||||||
|
BlockIoPpi,
|
||||||
|
&NumberBlockDevices
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 1; Index <= NumberBlockDevices && PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE; Index++) {
|
||||||
|
|
||||||
|
Status = BlockIoPpi->GetBlockDeviceMediaInfo (
|
||||||
|
PeiServices,
|
||||||
|
BlockIoPpi,
|
||||||
|
Index,
|
||||||
|
&Media
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status) || !Media.MediaPresent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockSize = (UINT32) Media.BlockSize;
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].LastBlock = Media.LastBlock;
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].IoAlign = 0;
|
||||||
|
//
|
||||||
|
// Not used here
|
||||||
|
//
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].Logical = FALSE;
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PartitionChecked = FALSE;
|
||||||
|
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockIo = BlockIoPpi;
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PhysicalDevNo = (UINT8) Index;
|
||||||
|
PrivateData->BlockDevice[PrivateData->BlockDeviceCount].DevType = Media.DeviceType;
|
||||||
|
|
||||||
|
PrivateData->BlockDeviceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Find out all logical devices
|
||||||
|
//
|
||||||
|
FatFindPartitions (PrivateData);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build up file system volume array
|
||||||
|
//
|
||||||
|
PrivateData->VolumeCount = 0;
|
||||||
|
for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
|
||||||
|
Volume.BlockDeviceNo = Index;
|
||||||
|
Status = FatGetBpbInfo (PrivateData, &Volume);
|
||||||
|
if (Status == EFI_SUCCESS) {
|
||||||
|
//
|
||||||
|
// Add the detected volume to the volume array
|
||||||
|
//
|
||||||
|
CopyMem (
|
||||||
|
(UINT8 *) &(PrivateData->Volume[PrivateData->VolumeCount]),
|
||||||
|
(UINT8 *) &Volume,
|
||||||
|
sizeof (PEI_FAT_VOLUME)
|
||||||
|
);
|
||||||
|
PrivateData->VolumeCount += 1;
|
||||||
|
if (PrivateData->VolumeCount >= PEI_FAT_MAX_VOLUME) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
BlockIo installation notification function. Find out all the current BlockIO
|
||||||
|
PPIs in the system and add them into private data. Assume there is
|
||||||
|
|
||||||
|
@param PeiServices General purpose services available to every
|
||||||
|
PEIM.
|
||||||
|
@param NotifyDescriptor The typedef structure of the notification
|
||||||
|
descriptor. Not used in this function.
|
||||||
|
@param Ppi The typedef structure of the PPI descriptor.
|
||||||
|
Not used in this function.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
BlockIoNotifyEntry (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
|
||||||
|
IN VOID *Ppi
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UpdateBlocksAndVolumes (mPrivateData);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Installs the Device Recovery Module PPI, Initialize BlockIo Ppi
|
||||||
|
installation notification
|
||||||
|
|
||||||
|
@param FileHandle Handle of the file being invoked. Type
|
||||||
|
EFI_PEI_FILE_HANDLE is defined in
|
||||||
|
FfsFindNextFile().
|
||||||
|
@param PeiServices Describes the list of possible PEI Services.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The entry point was executed successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is no enough memory to complete the
|
||||||
|
operations.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FatPeimEntry (
|
||||||
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||||
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address;
|
||||||
|
PEI_FAT_PRIVATE_DATA *PrivateData;
|
||||||
|
|
||||||
|
Status = PeiServicesRegisterForShadow (FileHandle);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PeiServicesAllocatePages (
|
||||||
|
EfiBootServicesCode,
|
||||||
|
(sizeof (PEI_FAT_PRIVATE_DATA) - 1) / PEI_FAT_MEMMORY_PAGE_SIZE + 1,
|
||||||
|
&Address
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateData = (PEI_FAT_PRIVATE_DATA *) (UINTN) Address;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize Private Data (to zero, as is required by subsequent operations)
|
||||||
|
//
|
||||||
|
ZeroMem ((UINT8 *) PrivateData, sizeof (PEI_FAT_PRIVATE_DATA));
|
||||||
|
|
||||||
|
PrivateData->Signature = PEI_FAT_PRIVATE_DATA_SIGNATURE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Installs Ppi
|
||||||
|
//
|
||||||
|
PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules;
|
||||||
|
PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo;
|
||||||
|
PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule;
|
||||||
|
|
||||||
|
PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
|
||||||
|
PrivateData->PpiDescriptor.Guid = &gEfiPeiDeviceRecoveryModulePpiGuid;
|
||||||
|
PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi;
|
||||||
|
|
||||||
|
Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Other initializations
|
||||||
|
//
|
||||||
|
PrivateData->BlockDeviceCount = 0;
|
||||||
|
|
||||||
|
UpdateBlocksAndVolumes (PrivateData);
|
||||||
|
|
||||||
|
//
|
||||||
|
// PrivateData is allocated now, set it to the module variable
|
||||||
|
//
|
||||||
|
mPrivateData = PrivateData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Installs Block Io Ppi notification function
|
||||||
|
//
|
||||||
|
PrivateData->NotifyDescriptor.Flags =
|
||||||
|
(
|
||||||
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
|
||||||
|
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
|
||||||
|
);
|
||||||
|
PrivateData->NotifyDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid;
|
||||||
|
PrivateData->NotifyDescriptor.Notify = BlockIoNotifyEntry;
|
||||||
|
return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of DXE capsules residing on the device.
|
||||||
|
|
||||||
|
This function searches for DXE capsules from the associated device and returns
|
||||||
|
the number and maximum size in bytes of the capsules discovered. Entry 1 is
|
||||||
|
assumed to be the highest load priority and entry N is assumed to be the lowest
|
||||||
|
priority.
|
||||||
|
|
||||||
|
@param[in] PeiServices General-purpose services that are available
|
||||||
|
to every PEIM
|
||||||
|
@param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
|
||||||
|
instance.
|
||||||
|
@param[out] NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On
|
||||||
|
output, *NumberRecoveryCapsules contains
|
||||||
|
the number of recovery capsule images
|
||||||
|
available for retrieval from this PEIM
|
||||||
|
instance.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS One or more capsules were discovered.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred.
|
||||||
|
@retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
GetNumberRecoveryCapsules (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
|
||||||
|
OUT UINTN *NumberRecoveryCapsules
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_PRIVATE_DATA *PrivateData;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN RecoveryCapsuleCount;
|
||||||
|
PEI_FILE_HANDLE Handle;
|
||||||
|
|
||||||
|
PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search each volume in the root directory for the Recovery capsule
|
||||||
|
//
|
||||||
|
RecoveryCapsuleCount = 0;
|
||||||
|
for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
|
||||||
|
Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecoveryCapsuleCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*NumberRecoveryCapsules = RecoveryCapsuleCount;
|
||||||
|
|
||||||
|
if (*NumberRecoveryCapsules == 0) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size and type of the requested recovery capsule.
|
||||||
|
|
||||||
|
This function gets the size and type of the capsule specified by CapsuleInstance.
|
||||||
|
|
||||||
|
@param[in] PeiServices General-purpose services that are available to every PEIM
|
||||||
|
@param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
|
||||||
|
instance.
|
||||||
|
@param[in] CapsuleInstance Specifies for which capsule instance to retrieve
|
||||||
|
the information. This parameter must be between
|
||||||
|
one and the value returned by GetNumberRecoveryCapsules()
|
||||||
|
in NumberRecoveryCapsules.
|
||||||
|
@param[out] Size A pointer to a caller-allocated UINTN in which
|
||||||
|
the size of the requested recovery module is
|
||||||
|
returned.
|
||||||
|
@param[out] CapsuleType A pointer to a caller-allocated EFI_GUID in which
|
||||||
|
the type of the requested recovery capsule is
|
||||||
|
returned. The semantic meaning of the value
|
||||||
|
returned is defined by the implementation.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS One or more capsules were discovered.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred.
|
||||||
|
@retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
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;
|
||||||
|
PEI_FAT_PRIVATE_DATA *PrivateData;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN BlockDeviceNo;
|
||||||
|
UINTN RecoveryCapsuleCount;
|
||||||
|
PEI_FILE_HANDLE Handle;
|
||||||
|
UINTN NumberRecoveryCapsules;
|
||||||
|
|
||||||
|
Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
|
||||||
|
CapsuleInstance = CapsuleInstance + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search each volume in the root directory for the Recovery capsule
|
||||||
|
//
|
||||||
|
RecoveryCapsuleCount = 0;
|
||||||
|
for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
|
||||||
|
Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
|
||||||
|
//
|
||||||
|
// Get file size
|
||||||
|
//
|
||||||
|
*Size = (UINTN) (((PEI_FAT_FILE *) Handle)->FileSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find corresponding physical block device
|
||||||
|
//
|
||||||
|
BlockDeviceNo = PrivateData->Volume[Index].BlockDeviceNo;
|
||||||
|
while (PrivateData->BlockDevice[BlockDeviceNo].Logical && BlockDeviceNo < PrivateData->BlockDeviceCount) {
|
||||||
|
BlockDeviceNo = PrivateData->BlockDevice[BlockDeviceNo].ParentDevNo;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Fill in the Capsule Type GUID according to the block device type
|
||||||
|
//
|
||||||
|
if (BlockDeviceNo < PrivateData->BlockDeviceCount) {
|
||||||
|
switch (PrivateData->BlockDevice[BlockDeviceNo].DevType) {
|
||||||
|
case LegacyFloppy:
|
||||||
|
CopyGuid (CapsuleType, &gRecoveryOnFatFloppyDiskGuid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IdeCDROM:
|
||||||
|
case IdeLS120:
|
||||||
|
CopyGuid (CapsuleType, &gRecoveryOnFatIdeDiskGuid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UsbMassStorage:
|
||||||
|
CopyGuid (CapsuleType, &gRecoveryOnFatUsbDiskGuid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecoveryCapsuleCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads a DXE capsule from some media into memory.
|
||||||
|
|
||||||
|
This function, by whatever mechanism, retrieves a DXE capsule from some device
|
||||||
|
and loads it into memory. Note that the published interface is device neutral.
|
||||||
|
|
||||||
|
@param[in] PeiServices General-purpose services that are available
|
||||||
|
to every PEIM
|
||||||
|
@param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
|
||||||
|
instance.
|
||||||
|
@param[in] CapsuleInstance Specifies which capsule instance to retrieve.
|
||||||
|
@param[out] Buffer Specifies a caller-allocated buffer in which
|
||||||
|
the requested recovery capsule will be returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The capsule was loaded correctly.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred.
|
||||||
|
@retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
LoadRecoveryCapsule (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
|
||||||
|
IN UINTN CapsuleInstance,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_PRIVATE_DATA *PrivateData;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN RecoveryCapsuleCount;
|
||||||
|
PEI_FILE_HANDLE Handle;
|
||||||
|
UINTN NumberRecoveryCapsules;
|
||||||
|
|
||||||
|
Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
|
||||||
|
CapsuleInstance = CapsuleInstance + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Search each volume in the root directory for the Recovery capsule
|
||||||
|
//
|
||||||
|
RecoveryCapsuleCount = 0;
|
||||||
|
for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
|
||||||
|
Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
|
||||||
|
|
||||||
|
Status = FatReadFile (
|
||||||
|
PrivateData,
|
||||||
|
Handle,
|
||||||
|
(UINTN) (((PEI_FAT_FILE *) Handle)->FileSize),
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecoveryCapsuleCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Finds the recovery file on a FAT volume.
|
||||||
|
This function finds the the recovery file named FileName on a specified FAT volume and returns
|
||||||
|
its FileHandle pointer.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global
|
||||||
|
variables.
|
||||||
|
@param VolumeIndex The index of the volume.
|
||||||
|
@param FileName The recovery file name to find.
|
||||||
|
@param Handle The output file handle.
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR Some error occured when operating the FAT
|
||||||
|
volume.
|
||||||
|
@retval EFI_NOT_FOUND The recovery file was not found.
|
||||||
|
@retval EFI_SUCCESS The recovery file was successfully found on the
|
||||||
|
FAT volume.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FindRecoveryFile (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN VolumeIndex,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
OUT PEI_FILE_HANDLE *Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_FILE Parent;
|
||||||
|
PEI_FAT_FILE *File;
|
||||||
|
|
||||||
|
File = &PrivateData->File;
|
||||||
|
|
||||||
|
//
|
||||||
|
// VolumeIndex must be less than PEI_FAT_MAX_VOLUME because PrivateData->VolumeCount
|
||||||
|
// cannot be larger than PEI_FAT_MAX_VOLUME when detecting recovery volume.
|
||||||
|
//
|
||||||
|
ASSERT (VolumeIndex < PEI_FAT_MAX_VOLUME);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Construct root directory file
|
||||||
|
//
|
||||||
|
Parent.IsFixedRootDir = (BOOLEAN) ((PrivateData->Volume[VolumeIndex].FatType == Fat32) ? FALSE : TRUE);
|
||||||
|
Parent.Attributes = FAT_ATTR_DIRECTORY;
|
||||||
|
Parent.CurrentPos = 0;
|
||||||
|
Parent.CurrentCluster = Parent.IsFixedRootDir ? 0 : PrivateData->Volume[VolumeIndex].RootDirCluster;
|
||||||
|
Parent.StartingCluster = Parent.CurrentCluster;
|
||||||
|
Parent.Volume = &PrivateData->Volume[VolumeIndex];
|
||||||
|
|
||||||
|
Status = FatSetFilePos (PrivateData, &Parent, 0);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Search for recovery capsule in root directory
|
||||||
|
//
|
||||||
|
Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
|
||||||
|
while (Status == EFI_SUCCESS) {
|
||||||
|
if (EngStriColl (PrivateData, FileName, File->FileName)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Handle = File;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/** @file
|
||||||
|
Definitions for FAT recovery PEIM API functions
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _FAT_API_H_
|
||||||
|
#define _FAT_API_H_
|
||||||
|
|
||||||
|
//
|
||||||
|
// API data structures
|
||||||
|
//
|
||||||
|
typedef VOID *PEI_FILE_HANDLE;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Fat12,
|
||||||
|
Fat16,
|
||||||
|
Fat32,
|
||||||
|
FatUnknown
|
||||||
|
} PEI_FAT_TYPE;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,144 @@
|
||||||
|
/** @file
|
||||||
|
FAT format data structures
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _FAT_FMT_H_
|
||||||
|
#define _FAT_FMT_H_
|
||||||
|
|
||||||
|
//
|
||||||
|
// Definitions
|
||||||
|
//
|
||||||
|
#define FAT_ATTR_READ_ONLY 0x01
|
||||||
|
#define FAT_ATTR_HIDDEN 0x02
|
||||||
|
#define FAT_ATTR_SYSTEM 0x04
|
||||||
|
#define FAT_ATTR_VOLUME_ID 0x08
|
||||||
|
#define FAT_ATTR_DIRECTORY 0x10
|
||||||
|
#define FAT_ATTR_ARCHIVE 0x20
|
||||||
|
#define FAT_ATTR_LFN (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID)
|
||||||
|
|
||||||
|
#define FAT_CLUSTER_SPECIAL ((-1 &~0xF) | 0x7)
|
||||||
|
#define FAT_CLUSTER_FREE 0
|
||||||
|
#define FAT_CLUSTER_RESERVED (FAT_CLUSTER_SPECIAL)
|
||||||
|
#define FAT_CLUSTER_BAD (FAT_CLUSTER_SPECIAL)
|
||||||
|
#define FAT_CLUSTER_LAST (-1)
|
||||||
|
|
||||||
|
#define DELETE_ENTRY_MARK 0xE5
|
||||||
|
#define EMPTY_ENTRY_MARK 0x00
|
||||||
|
|
||||||
|
#define FAT_CLUSTER_FUNCTIONAL(Cluster) (((Cluster) == 0) || ((Cluster) >= FAT_CLUSTER_SPECIAL))
|
||||||
|
#define FAT_CLUSTER_END_OF_CHAIN(Cluster) ((Cluster) > (FAT_CLUSTER_SPECIAL))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Directory Entry
|
||||||
|
//
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Day : 5;
|
||||||
|
UINT16 Month : 4;
|
||||||
|
UINT16 Year : 7; // From 1980
|
||||||
|
} FAT_DATE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 DoubleSecond : 5;
|
||||||
|
UINT16 Minute : 6;
|
||||||
|
UINT16 Hour : 5;
|
||||||
|
} FAT_TIME;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FAT_TIME Time;
|
||||||
|
FAT_DATE Date;
|
||||||
|
} FAT_DATE_TIME;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CHAR8 FileName[11]; // 8.3 filename
|
||||||
|
UINT8 Attributes;
|
||||||
|
UINT8 CaseFlag;
|
||||||
|
UINT8 CreateMillisecond; // (creation milliseconds - ignored)
|
||||||
|
FAT_DATE_TIME FileCreateTime;
|
||||||
|
FAT_DATE FileLastAccess;
|
||||||
|
UINT16 FileClusterHigh; // >= FAT32
|
||||||
|
FAT_DATE_TIME FileModificationTime;
|
||||||
|
UINT16 FileCluster;
|
||||||
|
UINT32 FileSize;
|
||||||
|
} FAT_DIRECTORY_ENTRY;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
//
|
||||||
|
// Boot Sector
|
||||||
|
//
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
UINT8 Ia32Jump[3];
|
||||||
|
CHAR8 OemId[8];
|
||||||
|
|
||||||
|
UINT16 SectorSize;
|
||||||
|
UINT8 SectorsPerCluster;
|
||||||
|
UINT16 ReservedSectors;
|
||||||
|
UINT8 NoFats;
|
||||||
|
UINT16 RootEntries; // < FAT32, root dir is fixed size
|
||||||
|
UINT16 Sectors;
|
||||||
|
UINT8 Media; // (ignored)
|
||||||
|
UINT16 SectorsPerFat; // < FAT32
|
||||||
|
UINT16 SectorsPerTrack; // (ignored)
|
||||||
|
UINT16 Heads; // (ignored)
|
||||||
|
UINT32 HiddenSectors; // (ignored)
|
||||||
|
UINT32 LargeSectors; // => FAT32
|
||||||
|
UINT8 PhysicalDriveNumber; // (ignored)
|
||||||
|
UINT8 CurrentHead; // holds boot_sector_dirty bit
|
||||||
|
UINT8 Signature; // (ignored)
|
||||||
|
CHAR8 Id[4];
|
||||||
|
CHAR8 FatLabel[11];
|
||||||
|
CHAR8 SystemId[8];
|
||||||
|
|
||||||
|
} PEI_FAT_BOOT_SECTOR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
UINT8 Ia32Jump[3];
|
||||||
|
CHAR8 OemId[8];
|
||||||
|
|
||||||
|
UINT16 SectorSize;
|
||||||
|
UINT8 SectorsPerCluster;
|
||||||
|
UINT16 ReservedSectors;
|
||||||
|
UINT8 NoFats;
|
||||||
|
UINT16 RootEntries; // < FAT32, root dir is fixed size
|
||||||
|
UINT16 Sectors;
|
||||||
|
UINT8 Media; // (ignored)
|
||||||
|
UINT16 SectorsPerFat; // < FAT32
|
||||||
|
UINT16 SectorsPerTrack; // (ignored)
|
||||||
|
UINT16 Heads; // (ignored)
|
||||||
|
UINT32 HiddenSectors; // (ignored)
|
||||||
|
UINT32 LargeSectors; // Used if Sectors==0
|
||||||
|
UINT32 LargeSectorsPerFat; // FAT32
|
||||||
|
UINT16 ExtendedFlags; // FAT32 (ignored)
|
||||||
|
UINT16 FsVersion; // FAT32 (ignored)
|
||||||
|
UINT32 RootDirFirstCluster; // FAT32
|
||||||
|
UINT16 FsInfoSector; // FAT32
|
||||||
|
UINT16 BackupBootSector; // FAT32
|
||||||
|
UINT8 Reserved[12]; // FAT32 (ignored)
|
||||||
|
UINT8 PhysicalDriveNumber; // (ignored)
|
||||||
|
UINT8 CurrentHead; // holds boot_sector_dirty bit
|
||||||
|
UINT8 Signature; // (ignored)
|
||||||
|
CHAR8 Id[4];
|
||||||
|
CHAR8 FatLabel[11];
|
||||||
|
CHAR8 SystemId[8];
|
||||||
|
|
||||||
|
} PEI_FAT_BOOT_SECTOR_EX;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,364 @@
|
||||||
|
/** @file
|
||||||
|
General purpose supporting routines for FAT recovery PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FatLitePeim.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CHAR_FAT_VALID 0x01
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts a union code character to upper case.
|
||||||
|
This functions converts a unicode character to upper case.
|
||||||
|
If the input Letter is not a lower-cased letter,
|
||||||
|
the original value is returned.
|
||||||
|
|
||||||
|
@param Letter The input unicode character.
|
||||||
|
|
||||||
|
@return The upper cased letter.
|
||||||
|
|
||||||
|
**/
|
||||||
|
CHAR16
|
||||||
|
ToUpper (
|
||||||
|
IN CHAR16 Letter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ('a' <= Letter && Letter <= 'z') {
|
||||||
|
Letter = (CHAR16) (Letter - 0x20);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads a block of data from the block device by calling
|
||||||
|
underlying Block I/O service.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param BlockDeviceNo The index for the block device number.
|
||||||
|
@param Lba The logic block address to read data from.
|
||||||
|
@param BufferSize The size of data in byte to read.
|
||||||
|
@param Buffer The buffer of the
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum
|
||||||
|
device number.
|
||||||
|
@retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address
|
||||||
|
of the block device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadBlock (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN BlockDeviceNo,
|
||||||
|
IN EFI_PEI_LBA Lba,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_BLOCK_DEVICE *BlockDev;
|
||||||
|
|
||||||
|
if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]);
|
||||||
|
|
||||||
|
if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BlockDev->Logical) {
|
||||||
|
//
|
||||||
|
// Status = BlockDev->ReadFunc
|
||||||
|
// (PrivateData->PeiServices, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer);
|
||||||
|
//
|
||||||
|
Status = BlockDev->BlockIo->ReadBlocks (
|
||||||
|
(EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
|
||||||
|
BlockDev->BlockIo,
|
||||||
|
BlockDev->PhysicalDevNo,
|
||||||
|
Lba,
|
||||||
|
BufferSize,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Status = FatReadDisk (
|
||||||
|
PrivateData,
|
||||||
|
BlockDev->ParentDevNo,
|
||||||
|
BlockDev->StartingPos + MultU64x32 (Lba, BlockDev->BlockSize),
|
||||||
|
BufferSize,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find a cache block designated to specific Block device and Lba.
|
||||||
|
If not found, invalidate an oldest one and use it. (LRU cache)
|
||||||
|
|
||||||
|
@param PrivateData the global memory map.
|
||||||
|
@param BlockDeviceNo the Block device.
|
||||||
|
@param Lba the Logical Block Address
|
||||||
|
@param CachePtr Ptr to the starting address of the memory holding the
|
||||||
|
data;
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetCacheBlock (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN BlockDeviceNo,
|
||||||
|
IN UINT64 Lba,
|
||||||
|
OUT CHAR8 **CachePtr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PEI_FAT_CACHE_BUFFER *CacheBuffer;
|
||||||
|
INTN Index;
|
||||||
|
STATIC UINT8 Seed;
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
CacheBuffer = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// go through existing cache buffers
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
|
||||||
|
CacheBuffer = &(PrivateData->CacheBuffer[Index]);
|
||||||
|
if (CacheBuffer->Valid && CacheBuffer->BlockDeviceNo == BlockDeviceNo && CacheBuffer->Lba == Lba) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index < PEI_FAT_CACHE_SIZE) {
|
||||||
|
*CachePtr = (CHAR8 *) CacheBuffer->Buffer;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We have to find an invalid cache buffer
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
|
||||||
|
if (!PrivateData->CacheBuffer[Index].Valid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Use the cache buffer
|
||||||
|
//
|
||||||
|
if (Index == PEI_FAT_CACHE_SIZE) {
|
||||||
|
Index = (Seed++) % PEI_FAT_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Current device ID should be less than maximum device ID.
|
||||||
|
//
|
||||||
|
if (BlockDeviceNo >= PEI_FAT_MAX_BLOCK_DEVICE) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheBuffer = &(PrivateData->CacheBuffer[Index]);
|
||||||
|
|
||||||
|
CacheBuffer->BlockDeviceNo = BlockDeviceNo;
|
||||||
|
CacheBuffer->Lba = Lba;
|
||||||
|
CacheBuffer->Size = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read in the data
|
||||||
|
//
|
||||||
|
Status = FatReadBlock (
|
||||||
|
PrivateData,
|
||||||
|
BlockDeviceNo,
|
||||||
|
Lba,
|
||||||
|
CacheBuffer->Size,
|
||||||
|
CacheBuffer->Buffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheBuffer->Valid = TRUE;
|
||||||
|
*CachePtr = (CHAR8 *) CacheBuffer->Buffer;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disk reading.
|
||||||
|
|
||||||
|
@param PrivateData the global memory map;
|
||||||
|
@param BlockDeviceNo the block device to read;
|
||||||
|
@param StartingAddress the starting address.
|
||||||
|
@param Size the amount of data to read.
|
||||||
|
@param Buffer the buffer holding the data
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadDisk (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN BlockDeviceNo,
|
||||||
|
IN UINT64 StartingAddress,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT32 BlockSize;
|
||||||
|
CHAR8 *BufferPtr;
|
||||||
|
CHAR8 *CachePtr;
|
||||||
|
UINT32 Offset;
|
||||||
|
UINT64 Lba;
|
||||||
|
UINT64 OverRunLba;
|
||||||
|
UINTN Amount;
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
BufferPtr = Buffer;
|
||||||
|
BlockSize = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read underrun
|
||||||
|
//
|
||||||
|
Lba = DivU64x32Remainder (StartingAddress, BlockSize, &Offset);
|
||||||
|
Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, Lba, &CachePtr);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Amount = Size < (BlockSize - Offset) ? Size : (BlockSize - Offset);
|
||||||
|
CopyMem (BufferPtr, CachePtr + Offset, Amount);
|
||||||
|
|
||||||
|
if (Size == Amount) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size -= Amount;
|
||||||
|
BufferPtr += Amount;
|
||||||
|
StartingAddress += Amount;
|
||||||
|
Lba += 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read aligned parts
|
||||||
|
//
|
||||||
|
OverRunLba = Lba + DivU64x32Remainder (Size, BlockSize, &Offset);
|
||||||
|
|
||||||
|
Size -= Offset;
|
||||||
|
Status = FatReadBlock (PrivateData, BlockDeviceNo, Lba, Size, BufferPtr);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferPtr += Size;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read overrun
|
||||||
|
//
|
||||||
|
if (Offset != 0) {
|
||||||
|
Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, OverRunLba, &CachePtr);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem (BufferPtr, CachePtr, Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This version is different from the version in Unicode collation
|
||||||
|
protocol in that this version strips off trailing blanks.
|
||||||
|
Converts an 8.3 FAT file name using an OEM character set
|
||||||
|
to a Null-terminated Unicode string.
|
||||||
|
Here does not expand DBCS FAT chars.
|
||||||
|
|
||||||
|
@param FatSize The size of the string Fat in bytes.
|
||||||
|
@param Fat A pointer to a Null-terminated string that contains
|
||||||
|
an 8.3 file name using an OEM character set.
|
||||||
|
@param Str A pointer to a Null-terminated Unicode string. The
|
||||||
|
string must be allocated in advance to hold FatSize
|
||||||
|
Unicode characters
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EngFatToStr (
|
||||||
|
IN UINTN FatSize,
|
||||||
|
IN CHAR8 *Fat,
|
||||||
|
OUT CHAR16 *Str
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CHAR16 *String;
|
||||||
|
|
||||||
|
String = Str;
|
||||||
|
//
|
||||||
|
// No DBCS issues, just expand and add null terminate to end of string
|
||||||
|
//
|
||||||
|
while (*Fat != 0 && FatSize != 0) {
|
||||||
|
*String = *Fat;
|
||||||
|
String += 1;
|
||||||
|
Fat += 1;
|
||||||
|
FatSize -= 1;
|
||||||
|
if (*Fat == ' ') {
|
||||||
|
*String = 0;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs a case-insensitive comparison of two Null-terminated Unicode strings.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param Str1 First string to perform case insensitive comparison.
|
||||||
|
@param Str2 Second string to perform case insensitive comparison.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
EngStriColl (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN CHAR16 *Str1,
|
||||||
|
IN CHAR16 *Str2
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CHAR16 UpperS1;
|
||||||
|
CHAR16 UpperS2;
|
||||||
|
|
||||||
|
UpperS1 = ToUpper (*Str1);
|
||||||
|
UpperS2 = ToUpper (*Str2);
|
||||||
|
while (*Str1 != 0) {
|
||||||
|
if (UpperS1 != UpperS2) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Str1++;
|
||||||
|
Str2++;
|
||||||
|
UpperS1 = ToUpper (*Str1);
|
||||||
|
UpperS2 = ToUpper (*Str2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (BOOLEAN) ((*Str2 != 0) ? FALSE : TRUE);
|
||||||
|
}
|
|
@ -0,0 +1,526 @@
|
||||||
|
/** @file
|
||||||
|
Data structures for FAT recovery PEIM
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _FAT_PEIM_H_
|
||||||
|
#define _FAT_PEIM_H_
|
||||||
|
|
||||||
|
#include <PiPei.h>
|
||||||
|
|
||||||
|
#include <Guid/RecoveryDevice.h>
|
||||||
|
#include <Ppi/BlockIo.h>
|
||||||
|
#include <Ppi/DeviceRecoveryModule.h>
|
||||||
|
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/PeimEntryPoint.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/PeiServicesTablePointerLib.h>
|
||||||
|
#include <Library/PeiServicesLib.h>
|
||||||
|
|
||||||
|
#include "FatLiteApi.h"
|
||||||
|
#include "FatLiteFmt.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Definitions
|
||||||
|
//
|
||||||
|
#define PEI_FAT_RECOVERY_CAPSULE_WITH_NT_EMULATOR L"fv0001.fv"
|
||||||
|
#define PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR L"fvmain.fv"
|
||||||
|
|
||||||
|
#define PEI_FAT_CACHE_SIZE 4
|
||||||
|
#define PEI_FAT_MAX_BLOCK_SIZE 8192
|
||||||
|
#define FAT_MAX_FILE_NAME_LENGTH 128
|
||||||
|
#define PEI_FAT_MAX_BLOCK_DEVICE 64
|
||||||
|
#define PEI_FAT_MAX_BLOCK_IO_PPI 32
|
||||||
|
#define PEI_FAT_MAX_VOLUME 64
|
||||||
|
|
||||||
|
#define PEI_FAT_MEMMORY_PAGE_SIZE 0x1000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data Structures
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The block device
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
UINT32 BlockSize;
|
||||||
|
UINT64 LastBlock;
|
||||||
|
UINT32 IoAlign;
|
||||||
|
BOOLEAN Logical;
|
||||||
|
BOOLEAN PartitionChecked;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Following fields only valid for logical device
|
||||||
|
//
|
||||||
|
CHAR8 PartitionFlag[8];
|
||||||
|
UINT64 StartingPos;
|
||||||
|
UINTN ParentDevNo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Following fields only valid for physical device
|
||||||
|
//
|
||||||
|
EFI_PEI_BLOCK_DEVICE_TYPE DevType;
|
||||||
|
//
|
||||||
|
// EFI_PEI_READ_BLOCKS ReadFunc;
|
||||||
|
//
|
||||||
|
EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIo;
|
||||||
|
UINT8 PhysicalDevNo;
|
||||||
|
} PEI_FAT_BLOCK_DEVICE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// the Volume structure
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
UINTN BlockDeviceNo;
|
||||||
|
UINTN VolumeNo;
|
||||||
|
UINT64 VolumeSize;
|
||||||
|
UINTN MaxCluster;
|
||||||
|
CHAR16 VolumeLabel[FAT_MAX_FILE_NAME_LENGTH];
|
||||||
|
PEI_FAT_TYPE FatType;
|
||||||
|
UINT64 FatPos;
|
||||||
|
UINT32 SectorSize;
|
||||||
|
UINT32 ClusterSize;
|
||||||
|
UINT64 FirstClusterPos;
|
||||||
|
UINT64 RootDirPos;
|
||||||
|
UINT32 RootEntries;
|
||||||
|
UINT32 RootDirCluster;
|
||||||
|
|
||||||
|
} PEI_FAT_VOLUME;
|
||||||
|
|
||||||
|
//
|
||||||
|
// File instance
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
PEI_FAT_VOLUME *Volume;
|
||||||
|
CHAR16 FileName[FAT_MAX_FILE_NAME_LENGTH];
|
||||||
|
|
||||||
|
BOOLEAN IsFixedRootDir;
|
||||||
|
|
||||||
|
UINT32 StartingCluster;
|
||||||
|
UINT32 CurrentPos;
|
||||||
|
UINT32 StraightReadAmount;
|
||||||
|
UINT32 CurrentCluster;
|
||||||
|
|
||||||
|
UINT8 Attributes;
|
||||||
|
UINT32 FileSize;
|
||||||
|
|
||||||
|
} PEI_FAT_FILE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cache Buffer
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
BOOLEAN Valid;
|
||||||
|
UINTN BlockDeviceNo;
|
||||||
|
UINT64 Lba;
|
||||||
|
UINT32 Lru;
|
||||||
|
UINT64 Buffer[PEI_FAT_MAX_BLOCK_SIZE / 8];
|
||||||
|
UINTN Size;
|
||||||
|
|
||||||
|
} PEI_FAT_CACHE_BUFFER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Private Data.
|
||||||
|
// This structure abstracts the whole memory usage in FAT PEIM.
|
||||||
|
// The entry point routine will get a chunk of memory (by whatever
|
||||||
|
// means) whose size is sizeof(PEI_FAT_PRIVATE_DATA), which is clean
|
||||||
|
// in both 32 and 64 bit environment. The boundary of the memory chunk
|
||||||
|
// should be 64bit aligned.
|
||||||
|
//
|
||||||
|
#define PEI_FAT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('p', 'f', 'a', 't')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
UINTN Signature;
|
||||||
|
EFI_PEI_DEVICE_RECOVERY_MODULE_PPI DeviceRecoveryPpi;
|
||||||
|
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
|
||||||
|
EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor;
|
||||||
|
|
||||||
|
UINT8 UnicodeCaseMap[0x300];
|
||||||
|
CHAR8 *EngUpperMap;
|
||||||
|
CHAR8 *EngLowerMap;
|
||||||
|
CHAR8 *EngInfoMap;
|
||||||
|
|
||||||
|
UINT64 BlockData[PEI_FAT_MAX_BLOCK_SIZE / 8];
|
||||||
|
UINTN BlockDeviceCount;
|
||||||
|
PEI_FAT_BLOCK_DEVICE BlockDevice[PEI_FAT_MAX_BLOCK_DEVICE];
|
||||||
|
UINTN VolumeCount;
|
||||||
|
PEI_FAT_VOLUME Volume[PEI_FAT_MAX_VOLUME];
|
||||||
|
PEI_FAT_FILE File;
|
||||||
|
PEI_FAT_CACHE_BUFFER CacheBuffer[PEI_FAT_CACHE_SIZE];
|
||||||
|
|
||||||
|
} PEI_FAT_PRIVATE_DATA;
|
||||||
|
|
||||||
|
#define PEI_FAT_PRIVATE_DATA_FROM_THIS(a) \
|
||||||
|
CR (a, PEI_FAT_PRIVATE_DATA, DeviceRecoveryPpi, PEI_FAT_PRIVATE_DATA_SIGNATURE)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Extract INT32 from char array
|
||||||
|
//
|
||||||
|
#define UNPACK_INT32(a) \
|
||||||
|
(INT32) ((((UINT8 *) a)[0] << 0) | (((UINT8 *) a)[1] << 8) | (((UINT8 *) a)[2] << 16) | (((UINT8 *) a)[3] << 24))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Extract UINT32 from char array
|
||||||
|
//
|
||||||
|
#define UNPACK_UINT32(a) \
|
||||||
|
(UINT32) ((((UINT8 *) a)[0] << 0) | (((UINT8 *) a)[1] << 8) | (((UINT8 *) a)[2] << 16) | (((UINT8 *) a)[3] << 24))
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// API functions
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
Finds the recovery file on a FAT volume.
|
||||||
|
This function finds the the recovery file named FileName on a specified FAT volume and returns
|
||||||
|
its FileHandle pointer.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global
|
||||||
|
variables.
|
||||||
|
@param VolumeIndex The index of the volume.
|
||||||
|
@param FileName The recovery file name to find.
|
||||||
|
@param Handle The output file handle.
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR Some error occured when operating the FAT
|
||||||
|
volume.
|
||||||
|
@retval EFI_NOT_FOUND The recovery file was not found.
|
||||||
|
@retval EFI_SUCCESS The recovery file was successfully found on the
|
||||||
|
FAT volume.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FindRecoveryFile (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN VolumeIndex,
|
||||||
|
IN CHAR16 *FileName,
|
||||||
|
OUT PEI_FILE_HANDLE *Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of DXE capsules residing on the device.
|
||||||
|
This function, by whatever mechanism, searches for DXE capsules from the associated device and
|
||||||
|
returns the number and maximum size in bytes of the capsules discovered.Entry 1 is assumed to be
|
||||||
|
the highest load priority and entry N is assumed to be the lowest priority.
|
||||||
|
|
||||||
|
@param PeiServices General-purpose services that are available to
|
||||||
|
every PEIM.
|
||||||
|
@param This Indicates the
|
||||||
|
EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance.
|
||||||
|
@param NumberRecoveryCapsules Pointer to a caller-allocated UINTN.On output,
|
||||||
|
*NumberRecoveryCapsules contains the number of
|
||||||
|
recovery capsule images available for retrieval
|
||||||
|
from this PEIM instance.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
GetNumberRecoveryCapsules (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
|
||||||
|
OUT UINTN *NumberRecoveryCapsules
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the size and type of the requested recovery capsule.
|
||||||
|
This function returns the size and type of the capsule specified by CapsuleInstance.
|
||||||
|
|
||||||
|
@param PeiServices General-purpose services that are available to
|
||||||
|
every PEIM.
|
||||||
|
@param This Indicates the
|
||||||
|
EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance.
|
||||||
|
@param CapsuleInstance Specifies for which capsule instance to
|
||||||
|
retrieve the information.T his parameter must
|
||||||
|
be between one and the value returned by
|
||||||
|
GetNumberRecoveryCapsules() in
|
||||||
|
NumberRecoveryCapsules.
|
||||||
|
@param Size A pointer to a caller-allocated UINTN in which
|
||||||
|
the size of the requested recovery module is
|
||||||
|
returned.
|
||||||
|
@param CapsuleType A pointer to a caller-allocated EFI_GUID in
|
||||||
|
which the type of the requested recovery
|
||||||
|
capsule is returned.T he semantic meaning of
|
||||||
|
the value returned is defined by the
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The capsule type and size were retrieved.
|
||||||
|
@retval EFI_INVALID_PARAMETER The input CapsuleInstance does not match any
|
||||||
|
discovered recovery capsule.
|
||||||
|
|
||||||
|
**/
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads a DXE capsule from some media into memory.
|
||||||
|
|
||||||
|
This function, by whatever mechanism, retrieves a DXE capsule from some device
|
||||||
|
and loads it into memory. Note that the published interface is device neutral.
|
||||||
|
|
||||||
|
@param[in] PeiServices General-purpose services that are available
|
||||||
|
to every PEIM
|
||||||
|
@param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
|
||||||
|
instance.
|
||||||
|
@param[in] CapsuleInstance Specifies which capsule instance to retrieve.
|
||||||
|
@param[out] Buffer Specifies a caller-allocated buffer in which
|
||||||
|
the requested recovery capsule will be returned.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The capsule was loaded correctly.
|
||||||
|
@retval EFI_DEVICE_ERROR A device error occurred.
|
||||||
|
@retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
LoadRecoveryCapsule (
|
||||||
|
IN EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
|
||||||
|
IN UINTN CapsuleInstance,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This version is different from the version in Unicode collation
|
||||||
|
protocol in that this version strips off trailing blanks.
|
||||||
|
Converts an 8.3 FAT file name using an OEM character set
|
||||||
|
to a Null-terminated Unicode string.
|
||||||
|
Here does not expand DBCS FAT chars.
|
||||||
|
|
||||||
|
@param FatSize The size of the string Fat in bytes.
|
||||||
|
@param Fat A pointer to a Null-terminated string that contains
|
||||||
|
an 8.3 file name using an OEM character set.
|
||||||
|
@param Str A pointer to a Null-terminated Unicode string. The
|
||||||
|
string must be allocated in advance to hold FatSize
|
||||||
|
Unicode characters
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EngFatToStr (
|
||||||
|
IN UINTN FatSize,
|
||||||
|
IN CHAR8 *Fat,
|
||||||
|
OUT CHAR16 *Str
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Performs a case-insensitive comparison of two Null-terminated Unicode strings.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param Str1 First string to perform case insensitive comparison.
|
||||||
|
@param Str2 Second string to perform case insensitive comparison.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
EngStriColl (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN CHAR16 *Str1,
|
||||||
|
IN CHAR16 *Str2
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads a block of data from the block device by calling
|
||||||
|
underlying Block I/O service.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param BlockDeviceNo The index for the block device number.
|
||||||
|
@param Lba The logic block address to read data from.
|
||||||
|
@param BufferSize The size of data in byte to read.
|
||||||
|
@param Buffer The buffer of the
|
||||||
|
|
||||||
|
@retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum
|
||||||
|
device number.
|
||||||
|
@retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address
|
||||||
|
of the block device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadBlock (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN BlockDeviceNo,
|
||||||
|
IN EFI_PEI_LBA Lba,
|
||||||
|
IN UINTN BufferSize,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if there is a valid FAT in the corresponding Block device
|
||||||
|
of the volume and if yes, fill in the relevant fields for the
|
||||||
|
volume structure. Note there should be a valid Block device number
|
||||||
|
already set.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global
|
||||||
|
variables.
|
||||||
|
@param Volume On input, the BlockDeviceNumber field of the
|
||||||
|
Volume should be a valid value. On successful
|
||||||
|
output, all fields except the VolumeNumber
|
||||||
|
field is initialized.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS A FAT is found and the volume structure is
|
||||||
|
initialized.
|
||||||
|
@retval EFI_NOT_FOUND There is no FAT on the corresponding device.
|
||||||
|
@retval EFI_DEVICE_ERROR There is something error while accessing device.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetBpbInfo (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN OUT PEI_FAT_VOLUME *Volume
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the next cluster in the cluster chain.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param Volume The volume
|
||||||
|
@param Cluster The cluster
|
||||||
|
@param NextCluster The cluster number of the next cluster
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The address is got
|
||||||
|
@retval EFI_INVALID_PARAMETER ClusterNo exceeds the MaxCluster of the volume.
|
||||||
|
@retval EFI_DEVICE_ERROR Read disk error
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatGetNextCluster (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_VOLUME *Volume,
|
||||||
|
IN UINT32 Cluster,
|
||||||
|
OUT UINT32 *NextCluster
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disk reading.
|
||||||
|
|
||||||
|
@param PrivateData the global memory map;
|
||||||
|
@param BlockDeviceNo the block device to read;
|
||||||
|
@param StartingAddress the starting address.
|
||||||
|
@param Size the amount of data to read.
|
||||||
|
@param Buffer the buffer holding the data
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadDisk (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN BlockDeviceNo,
|
||||||
|
IN UINT64 StartingAddress,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set a file's CurrentPos and CurrentCluster, then compute StraightReadAmount.
|
||||||
|
|
||||||
|
@param PrivateData the global memory map
|
||||||
|
@param File the file
|
||||||
|
@param Pos the Position which is offset from the file's
|
||||||
|
CurrentPos
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Success.
|
||||||
|
@retval EFI_INVALID_PARAMETER Pos is beyond file's size.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatSetFilePos (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *File,
|
||||||
|
IN UINT32 Pos
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads file data. Updates the file's CurrentPos.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param File The file.
|
||||||
|
@param Size The amount of data to read.
|
||||||
|
@param Buffer The buffer storing the data.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data is read.
|
||||||
|
@retval EFI_INVALID_PARAMETER File is invalid.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadFile (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *File,
|
||||||
|
IN UINTN Size,
|
||||||
|
OUT VOID *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function reads the next item in the parent directory and
|
||||||
|
initializes the output parameter SubFile (CurrentPos is initialized to 0).
|
||||||
|
The function updates the CurrentPos of the parent dir to after the item read.
|
||||||
|
If no more items were found, the function returns EFI_NOT_FOUND.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables
|
||||||
|
@param ParentDir The parent directory.
|
||||||
|
@param SubFile The File structure containing the sub file that
|
||||||
|
is caught.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The next sub file is obtained.
|
||||||
|
@retval EFI_INVALID_PARAMETER The ParentDir is not a directory.
|
||||||
|
@retval EFI_NOT_FOUND No more sub file exists.
|
||||||
|
@retval EFI_DEVICE_ERROR Something error while accessing media.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FatReadNextDirectoryEntry (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN PEI_FAT_FILE *ParentDir,
|
||||||
|
OUT PEI_FAT_FILE *SubFile
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds partitions (logical devices) in physical block devices.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FatFindPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // _FAT_PEIM_H_
|
|
@ -0,0 +1,74 @@
|
||||||
|
## @file
|
||||||
|
# Lite Fat driver only used in Pei Phase.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials are licensed and made available
|
||||||
|
# under the terms and conditions of the BSD License which accompanies this
|
||||||
|
# distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = FatPei
|
||||||
|
FILE_GUID = 5B60CCFD-1011-4BCF-B7D1-BB99CA96A603
|
||||||
|
MODULE_TYPE = PEIM
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
|
||||||
|
ENTRY_POINT = FatPeimEntry
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
Part.c
|
||||||
|
FatLiteApi.c
|
||||||
|
FatLiteLib.c
|
||||||
|
FatLiteAccess.c
|
||||||
|
FatLiteApi.h
|
||||||
|
FatLitePeim.h
|
||||||
|
FatLiteFmt.h
|
||||||
|
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
PcdLib
|
||||||
|
BaseMemoryLib
|
||||||
|
PeimEntryPoint
|
||||||
|
BaseLib
|
||||||
|
DebugLib
|
||||||
|
PeiServicesTablePointerLib
|
||||||
|
PeiServicesLib
|
||||||
|
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gRecoveryOnFatUsbDiskGuid # ALWAYS_CONSUMED
|
||||||
|
gRecoveryOnFatIdeDiskGuid # ALWAYS_CONSUMED
|
||||||
|
gRecoveryOnFatFloppyDiskGuid # ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
|
||||||
|
[Ppis]
|
||||||
|
gEfiPeiVirtualBlockIoPpiGuid # PPI_NOTIFY SOMETIMES_CONSUMED
|
||||||
|
gEfiPeiDeviceRecoveryModulePpiGuid # SOMETIMES_PRODUCED
|
||||||
|
|
||||||
|
|
||||||
|
[FeaturePcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
|
||||||
|
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,466 @@
|
||||||
|
/** @file
|
||||||
|
Routines supporting partition discovery and
|
||||||
|
logical device reading
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available
|
||||||
|
under the terms and conditions of the BSD License which accompanies this
|
||||||
|
distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <IndustryStandard/Mbr.h>
|
||||||
|
#include <IndustryStandard/ElTorito.h>
|
||||||
|
#include "FatLitePeim.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds Eltorito partitions. Main algorithm
|
||||||
|
is ported from DXE partition driver.
|
||||||
|
|
||||||
|
@param PrivateData The global memory map
|
||||||
|
@param ParentBlockDevNo The parent block device
|
||||||
|
|
||||||
|
@retval TRUE New partitions are detected and logical block devices
|
||||||
|
are added to block device array
|
||||||
|
@retval FALSE No New partitions are added;
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
FatFindEltoritoPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN ParentBlockDevNo
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds Mbr partitions. Main algorithm
|
||||||
|
is ported from DXE partition driver.
|
||||||
|
|
||||||
|
@param PrivateData The global memory map
|
||||||
|
@param ParentBlockDevNo The parent block device
|
||||||
|
|
||||||
|
@retval TRUE New partitions are detected and logical block devices
|
||||||
|
are added to block device array
|
||||||
|
@retval FALSE No New partitions are added;
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
FatFindMbrPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN ParentBlockDevNo
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds partitions (logical devices) in physical block devices.
|
||||||
|
|
||||||
|
@param PrivateData Global memory map for accessing global variables.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FatFindPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BOOLEAN Found;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
do {
|
||||||
|
Found = FALSE;
|
||||||
|
|
||||||
|
for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
|
||||||
|
if (!PrivateData->BlockDevice[Index].PartitionChecked) {
|
||||||
|
Found = FatFindMbrPartitions (PrivateData, Index);
|
||||||
|
if (!Found) {
|
||||||
|
Found = FatFindEltoritoPartitions (PrivateData, Index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (Found && PrivateData->BlockDeviceCount <= PEI_FAT_MAX_BLOCK_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds Eltorito partitions. Main algorithm
|
||||||
|
is ported from DXE partition driver.
|
||||||
|
|
||||||
|
@param PrivateData The global memory map
|
||||||
|
@param ParentBlockDevNo The parent block device
|
||||||
|
|
||||||
|
@retval TRUE New partitions are detected and logical block devices
|
||||||
|
are added to block device array
|
||||||
|
@retval FALSE No New partitions are added;
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
FatFindEltoritoPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN ParentBlockDevNo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
BOOLEAN Found;
|
||||||
|
PEI_FAT_BLOCK_DEVICE *BlockDev;
|
||||||
|
PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
|
||||||
|
UINT32 VolDescriptorLba;
|
||||||
|
UINT32 Lba;
|
||||||
|
CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
|
||||||
|
ELTORITO_CATALOG *Catalog;
|
||||||
|
UINTN Check;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN MaxIndex;
|
||||||
|
UINT16 *CheckBuffer;
|
||||||
|
UINT32 SubBlockSize;
|
||||||
|
UINT32 SectorCount;
|
||||||
|
UINT32 VolSpaceSize;
|
||||||
|
|
||||||
|
if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Found = FALSE;
|
||||||
|
ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
|
||||||
|
VolSpaceSize = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// CD_ROM has the fixed block size as 2048 bytes
|
||||||
|
//
|
||||||
|
if (ParentBlockDev->BlockSize != 2048) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
|
||||||
|
Catalog = (ELTORITO_CATALOG *) VolDescriptor;
|
||||||
|
|
||||||
|
//
|
||||||
|
// the ISO-9660 volume descriptor starts at 32k on the media
|
||||||
|
// and CD_ROM has the fixed block size as 2048 bytes, so...
|
||||||
|
//
|
||||||
|
VolDescriptorLba = 15;
|
||||||
|
//
|
||||||
|
// ((16*2048) / Media->BlockSize) - 1;
|
||||||
|
//
|
||||||
|
// Loop: handle one volume descriptor per time
|
||||||
|
//
|
||||||
|
while (TRUE) {
|
||||||
|
|
||||||
|
VolDescriptorLba += 1;
|
||||||
|
if (VolDescriptorLba > ParentBlockDev->LastBlock) {
|
||||||
|
//
|
||||||
|
// We are pointing past the end of the device so exit
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatReadBlock (
|
||||||
|
PrivateData,
|
||||||
|
ParentBlockDevNo,
|
||||||
|
VolDescriptorLba,
|
||||||
|
ParentBlockDev->BlockSize,
|
||||||
|
VolDescriptor
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check for valid volume descriptor signature
|
||||||
|
//
|
||||||
|
if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
|
||||||
|
CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
// end of Volume descriptor list
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
|
||||||
|
//
|
||||||
|
if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
|
||||||
|
VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Is it an El Torito volume descriptor?
|
||||||
|
//
|
||||||
|
if (CompareMem (
|
||||||
|
VolDescriptor->BootRecordVolume.SystemId,
|
||||||
|
CDVOL_ELTORITO_ID,
|
||||||
|
sizeof (CDVOL_ELTORITO_ID) - 1
|
||||||
|
) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Read in the boot El Torito boot catalog
|
||||||
|
//
|
||||||
|
Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
|
||||||
|
if (Lba > ParentBlockDev->LastBlock) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = FatReadBlock (
|
||||||
|
PrivateData,
|
||||||
|
ParentBlockDevNo,
|
||||||
|
Lba,
|
||||||
|
ParentBlockDev->BlockSize,
|
||||||
|
Catalog
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We don't care too much about the Catalog header's contents, but we do want
|
||||||
|
// to make sure it looks like a Catalog header
|
||||||
|
//
|
||||||
|
if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Check = 0;
|
||||||
|
CheckBuffer = (UINT16 *) Catalog;
|
||||||
|
for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
|
||||||
|
Check += CheckBuffer[Index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Check & 0xFFFF) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
|
||||||
|
for (Index = 1; Index < MaxIndex; Index += 1) {
|
||||||
|
//
|
||||||
|
// Next entry
|
||||||
|
//
|
||||||
|
Catalog += 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check this entry
|
||||||
|
//
|
||||||
|
if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubBlockSize = 512;
|
||||||
|
SectorCount = Catalog->Boot.SectorCount;
|
||||||
|
|
||||||
|
switch (Catalog->Boot.MediaType) {
|
||||||
|
|
||||||
|
case ELTORITO_NO_EMULATION:
|
||||||
|
SubBlockSize = ParentBlockDev->BlockSize;
|
||||||
|
SectorCount = Catalog->Boot.SectorCount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELTORITO_HARD_DISK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELTORITO_12_DISKETTE:
|
||||||
|
SectorCount = 0x50 * 0x02 * 0x0F;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELTORITO_14_DISKETTE:
|
||||||
|
SectorCount = 0x50 * 0x02 * 0x12;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ELTORITO_28_DISKETTE:
|
||||||
|
SectorCount = 0x50 * 0x02 * 0x24;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SectorCount = 0;
|
||||||
|
SubBlockSize = ParentBlockDev->BlockSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SectorCount < 2) {
|
||||||
|
SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Register this partition
|
||||||
|
//
|
||||||
|
if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
|
||||||
|
|
||||||
|
Found = TRUE;
|
||||||
|
|
||||||
|
BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
|
||||||
|
|
||||||
|
BlockDev->BlockSize = SubBlockSize;
|
||||||
|
BlockDev->LastBlock = SectorCount - 1;
|
||||||
|
BlockDev->IoAlign = ParentBlockDev->IoAlign;
|
||||||
|
BlockDev->Logical = TRUE;
|
||||||
|
BlockDev->PartitionChecked = FALSE;
|
||||||
|
BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);
|
||||||
|
BlockDev->ParentDevNo = ParentBlockDevNo;
|
||||||
|
|
||||||
|
PrivateData->BlockDeviceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParentBlockDev->PartitionChecked = TRUE;
|
||||||
|
|
||||||
|
return Found;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test to see if the Mbr buffer is a valid MBR
|
||||||
|
|
||||||
|
@param Mbr Parent Handle
|
||||||
|
@param LastLba Last Lba address on the device.
|
||||||
|
|
||||||
|
@retval TRUE Mbr is a Valid MBR
|
||||||
|
@retval FALSE Mbr is not a Valid MBR
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
PartitionValidMbr (
|
||||||
|
IN MASTER_BOOT_RECORD *Mbr,
|
||||||
|
IN EFI_PEI_LBA LastLba
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 StartingLBA;
|
||||||
|
UINT32 EndingLBA;
|
||||||
|
UINT32 NewEndingLBA;
|
||||||
|
INTN Index1;
|
||||||
|
INTN Index2;
|
||||||
|
BOOLEAN MbrValid;
|
||||||
|
|
||||||
|
if (Mbr->Signature != MBR_SIGNATURE) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// The BPB also has this signature, so it can not be used alone.
|
||||||
|
//
|
||||||
|
MbrValid = FALSE;
|
||||||
|
for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
|
||||||
|
if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MbrValid = TRUE;
|
||||||
|
StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
|
||||||
|
EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
|
||||||
|
if (EndingLBA > LastLba) {
|
||||||
|
//
|
||||||
|
// Compatability Errata:
|
||||||
|
// Some systems try to hide drive space with thier INT 13h driver
|
||||||
|
// This does not hide space from the OS driver. This means the MBR
|
||||||
|
// that gets created from DOS is smaller than the MBR created from
|
||||||
|
// a real OS (NT & Win98). This leads to BlockIo->LastBlock being
|
||||||
|
// wrong on some systems FDISKed by the OS.
|
||||||
|
//
|
||||||
|
// return FALSE Because no block devices on a system are implemented
|
||||||
|
// with INT 13h
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
|
||||||
|
if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
|
||||||
|
if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
|
||||||
|
//
|
||||||
|
// This region overlaps with the Index1'th region
|
||||||
|
//
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Non of the regions overlapped so MBR is O.K.
|
||||||
|
//
|
||||||
|
return MbrValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function finds Mbr partitions. Main algorithm
|
||||||
|
is ported from DXE partition driver.
|
||||||
|
|
||||||
|
@param PrivateData The global memory map
|
||||||
|
@param ParentBlockDevNo The parent block device
|
||||||
|
|
||||||
|
@retval TRUE New partitions are detected and logical block devices
|
||||||
|
are added to block device array
|
||||||
|
@retval FALSE No New partitions are added;
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
FatFindMbrPartitions (
|
||||||
|
IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
||||||
|
IN UINTN ParentBlockDevNo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
MASTER_BOOT_RECORD *Mbr;
|
||||||
|
UINTN Index;
|
||||||
|
BOOLEAN Found;
|
||||||
|
PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
|
||||||
|
PEI_FAT_BLOCK_DEVICE *BlockDev;
|
||||||
|
|
||||||
|
if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
|
||||||
|
|
||||||
|
Found = FALSE;
|
||||||
|
Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
|
||||||
|
|
||||||
|
Status = FatReadBlock (
|
||||||
|
PrivateData,
|
||||||
|
ParentBlockDevNo,
|
||||||
|
0,
|
||||||
|
ParentBlockDev->BlockSize,
|
||||||
|
Mbr
|
||||||
|
);
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We have a valid mbr - add each partition
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
|
||||||
|
if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
|
||||||
|
//
|
||||||
|
// Don't use null MBR entries
|
||||||
|
//
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Register this partition
|
||||||
|
//
|
||||||
|
if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
|
||||||
|
|
||||||
|
Found = TRUE;
|
||||||
|
|
||||||
|
BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
|
||||||
|
|
||||||
|
BlockDev->BlockSize = MBR_SIZE;
|
||||||
|
BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
|
||||||
|
BlockDev->IoAlign = ParentBlockDev->IoAlign;
|
||||||
|
BlockDev->Logical = TRUE;
|
||||||
|
BlockDev->PartitionChecked = FALSE;
|
||||||
|
BlockDev->StartingPos = MultU64x32 (
|
||||||
|
UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
|
||||||
|
ParentBlockDev->BlockSize
|
||||||
|
);
|
||||||
|
BlockDev->ParentDevNo = ParentBlockDevNo;
|
||||||
|
|
||||||
|
PrivateData->BlockDeviceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Done:
|
||||||
|
|
||||||
|
ParentBlockDev->PartitionChecked = TRUE;
|
||||||
|
return Found;
|
||||||
|
}
|
|
@ -26,6 +26,11 @@
|
||||||
BUILD_TARGETS = DEBUG|RELEASE
|
BUILD_TARGETS = DEBUG|RELEASE
|
||||||
SKUID_IDENTIFIER = DEFAULT
|
SKUID_IDENTIFIER = DEFAULT
|
||||||
|
|
||||||
|
[BuildOptions]
|
||||||
|
GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
|
||||||
|
INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
|
||||||
|
MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
#
|
#
|
||||||
# Entry Point Libraries
|
# Entry Point Libraries
|
||||||
|
@ -46,6 +51,14 @@
|
||||||
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
||||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||||
|
|
||||||
|
[LibraryClasses.common.PEIM]
|
||||||
|
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
|
||||||
|
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
|
||||||
|
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||||
|
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
|
||||||
|
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
|
||||||
|
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
|
||||||
|
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
#
|
#
|
||||||
# Components Section - list of the modules and components that will be processed by compilation
|
# Components Section - list of the modules and components that will be processed by compilation
|
||||||
|
@ -66,4 +79,5 @@
|
||||||
###################################################################################################
|
###################################################################################################
|
||||||
|
|
||||||
[Components]
|
[Components]
|
||||||
|
FatPkg/FatPei/FatPei.inf
|
||||||
FatPkg/EnhancedFatDxe/Fat.inf
|
FatPkg/EnhancedFatDxe/Fat.inf
|
||||||
|
|
Loading…
Reference in New Issue