CHAR8 *gCwd = NULL;
+CONST EFI_GUID gZeroGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
#define EFI_OPEN_FILE_GUARD_HEADER 0x4B4D4641
#define EFI_OPEN_FILE_GUARD_FOOTER 0x444D5A56
return Status;
}
+ // Get FVB Info about the handle
+ Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
+ if (!EFI_ERROR (Status)) {
+ Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart);
+ if (!EFI_ERROR (Status)) {
+ for (Lba = 0, File->FvSize = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) {
+ Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ }
+
+
DevicePath = DevicePathFromHandle (File->EfiHandle);
if (*FileName == '\0') {
File->DevicePath = DuplicateDevicePath (DevicePath);
+ File->Size = File->FvSize;
+ File->MaxPosition = File->Size;
} else {
Key = 0;
do {
&File->Size
);
if (!EFI_ERROR (GetNextFileStatus)) {
- Section = NULL;
-
// Compare GUID first
Status = CompareGuidToString (&File->FvNameGuid, FileName);
if (!EFI_ERROR(Status)) {
break;
}
+ Section = NULL;
Status = File->Fv->ReadSection (
File->Fv,
&File->FvNameGuid,
return GetNextFileStatus;
}
+ if (OpenMode != EFI_SECTION_ALL) {
+ // Calculate the size of the section we are targeting
+ Section = NULL;
+ File->Size = 0;
+ Status = File->Fv->ReadSection (
+ File->Fv,
+ &File->FvNameGuid,
+ OpenMode,
+ 0,
+ &Section,
+ &File->Size,
+ &AuthenticationStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
File->MaxPosition = File->Size;
EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid);
File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode);
}
-
- // Get FVB Info about the handle
- Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
- if (!EFI_ERROR (Status)) {
- Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart);
- if (!EFI_ERROR (Status)) {
- for (Lba = 0, File->FvSize = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) {
- Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- break;
- }
- }
- }
- }
-
+
// FVB not required if FV was soft loaded...
return EFI_SUCCESS;
}
UINTN Size;
EFI_IP_ADDRESS Ip;
CHAR8 *CwdPlusPathName;
+ UINTN Index;
+ EFI_SECTION_TYPE ModifiedSectionType;
EblUpdateDeviceLists ();
File = &FileData;
ZeroMem (File, sizeof (EFI_OPEN_FILE));
- File->FvSectionType = SectionType;
StrLen = AsciiStrSize (PathName);
if (StrLen <= 1) {
}
}
- if (FileStart == StrLen) {
- if (gCwd == NULL) {
- // No CWD
- return NULL;
- }
-
- // We could add a current working diretory concept
- CwdPlusPathName = AllocatePool (AsciiStrSize (gCwd) + AsciiStrSize (PathName));
- if (CwdPlusPathName == NULL) {
- return NULL;
- }
-
- if ((PathName[0] == '/') || (PathName[0] == '\\')) {
- // PathName starts in / so this means we go to the root of the device in the CWD.
- CwdPlusPathName[0] = '\0';
- for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) {
- CwdPlusPathName[FileStart] = gCwd[FileStart];
- if (gCwd[FileStart] == ':') {
- FileStart++;
- CwdPlusPathName[FileStart] = '\0';
- break;
- }
- }
- } else {
- AsciiStrCpy (CwdPlusPathName, gCwd);
- StrLen = AsciiStrLen (gCwd);
- if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) {
- AsciiStrCat (CwdPlusPathName, "\\");
- }
- }
-
- AsciiStrCat (CwdPlusPathName, PathName);
- if (AsciiStrStr (CwdPlusPathName, ":") == NULL) {
- // Extra error check to make sure we don't recusre and blow stack
- return NULL;
- }
-
- File = EfiOpen (CwdPlusPathName, OpenMode, SectionType);
- FreePool (CwdPlusPathName);
- return File;
- }
-
//
// Matching volume name has precedence over handle based names
//
VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber);
if (!VolumeNameMatch) {
+ if (FileStart == StrLen) {
+ // No Volume name or device name, so try Current Working Directory
+ if (gCwd == NULL) {
+ // No CWD
+ return NULL;
+ }
+
+ // We could add a current working diretory concept
+ CwdPlusPathName = AllocatePool (AsciiStrSize (gCwd) + AsciiStrSize (PathName));
+ if (CwdPlusPathName == NULL) {
+ return NULL;
+ }
+
+ if ((PathName[0] == '/') || (PathName[0] == '\\')) {
+ // PathName starts in / so this means we go to the root of the device in the CWD.
+ CwdPlusPathName[0] = '\0';
+ for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) {
+ CwdPlusPathName[FileStart] = gCwd[FileStart];
+ if (gCwd[FileStart] == ':') {
+ FileStart++;
+ CwdPlusPathName[FileStart] = '\0';
+ break;
+ }
+ }
+ } else {
+ AsciiStrCpy (CwdPlusPathName, gCwd);
+ StrLen = AsciiStrLen (gCwd);
+ if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) {
+ AsciiStrCat (CwdPlusPathName, "\\");
+ }
+ }
+
+ AsciiStrCat (CwdPlusPathName, PathName);
+ if (AsciiStrStr (CwdPlusPathName, ":") == NULL) {
+ // Extra error check to make sure we don't recusre and blow stack
+ return NULL;
+ }
+
+ File = EfiOpen (CwdPlusPathName, OpenMode, SectionType);
+ FreePool (CwdPlusPathName);
+ return File;
+ }
+
DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName);
}
// Skip leading / as its not really needed for the FV since no directories are supported
FileStart++;
}
- Status = EblFvFileDevicePath (File, &PathName[FileStart], OpenMode);
+
+ // Check for 2nd :
+ ModifiedSectionType = SectionType;
+ for (Index = FileStart; PathName[Index] != '\0'; Index++) {
+ if (PathName[Index] == ':') {
+ // Support fv0:\DxeCore:0x10
+ // This means open the PE32 Section of the file
+ ModifiedSectionType = AsciiStrHexToUintn (&PathName[Index + 1]);
+ PathName[Index] = '\0';
+ }
+ }
+ File->FvSectionType = ModifiedSectionType;
+ Status = EblFvFileDevicePath (File, &PathName[FileStart], ModifiedSectionType);
}
} else if ((*PathName == 'A') || (*PathName == 'a')) {
// Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE
UINTN Offset;
UINTN Chunk = FILE_COPY_CHUNK;
- Source = EfiOpen(SourceFile, EFI_FILE_MODE_READ, 0);
+ Source = EfiOpen (SourceFile, EFI_FILE_MODE_READ, 0);
if (Source == NULL) {
AsciiPrint("Source file open error.\n");
Status = EFI_NOT_FOUND;
goto Exit;
}
- Destination = EfiOpen(DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
+ Destination = EfiOpen (DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
if (Destination == NULL) {
AsciiPrint("Destination file open error.\n");
Status = EFI_NOT_FOUND;
}
if ((File->Type == EfiOpenLoadFile) ||
- ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE))) {
+ ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE)) ||
+ ((File->Type == EfiOpenFirmwareVolume) && (File->IsBufferValid == TRUE))) {
EblFreePool(File->Buffer);
}
return EFI_INVALID_PARAMETER;
}
- if (File->Type == EfiOpenLoadFile || File->Type == EfiOpenFirmwareVolume) {
- // LoadFile and FV do not support Seek
+ if (File->Type == EfiOpenLoadFile) {
+ // LoadFile does not support Seek
return EFI_UNSUPPORTED;
}
}
switch (File->Type) {
- case EfiOpenMemoryBuffer:
- CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
- File->CurrentPosition += *BufferSize;
- Status = EFI_SUCCESS;
- break;
-
case EfiOpenLoadFile:
// Figure out the File->Size
EfiTell (File, NULL);
break;
case EfiOpenFirmwareVolume:
- if (File->FvSectionType == EFI_SECTION_ALL) {
- Status = File->Fv->ReadFile (
- File->Fv,
- &File->FvNameGuid,
- &Buffer,
- BufferSize,
- &File->FvType,
- &File->FvAttributes,
- &AuthenticationStatus
- );
+ if (CompareGuid (&File->FvNameGuid, &gZeroGuid)) {
+ // This is the entire FV device, so treat like a memory buffer
+ CopyMem (Buffer, (VOID *)(UINTN)(File->FvStart + File->CurrentPosition), *BufferSize);
+ File->CurrentPosition += *BufferSize;
+ Status = EFI_SUCCESS;
} else {
- Status = File->Fv->ReadSection (
- File->Fv,
- &File->FvNameGuid,
- File->FvSectionType,
- 0,
- &Buffer,
- BufferSize,
- &AuthenticationStatus
- );
+ if (File->Buffer == NULL) {
+ if (File->FvSectionType == EFI_SECTION_ALL) {
+ Status = File->Fv->ReadFile (
+ File->Fv,
+ &File->FvNameGuid,
+ (VOID **)&File->Buffer,
+ &File->Size,
+ &File->FvType,
+ &File->FvAttributes,
+ &AuthenticationStatus
+ );
+ } else {
+ Status = File->Fv->ReadSection (
+ File->Fv,
+ &File->FvNameGuid,
+ File->FvSectionType,
+ 0,
+ (VOID **)&File->Buffer,
+ &File->Size,
+ &AuthenticationStatus
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ File->IsBufferValid = TRUE;
+ }
+ // Operate on the cached buffer so Seek will work
+ CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
+ File->CurrentPosition += *BufferSize;
+ Status = EFI_SUCCESS;
}
break;
+
+ case EfiOpenMemoryBuffer:
+ CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize);
+ File->CurrentPosition += *BufferSize;
+ Status = EFI_SUCCESS;
+ break;
case EfiOpenFileSystem:
Status = File->FsFileHandle->Read (File->FsFileHandle, BufferSize, Buffer);
// Use the info returned from EfiOpen as it can add in CWD if needed. So Cwd could be
// relative to the current gCwd or not.
- gCwd = AllocatePool (AsciiStrSize (File->DeviceName) + AsciiStrSize (File->FileName) + 1);
+ gCwd = AllocatePool (AsciiStrSize (File->DeviceName) + AsciiStrSize (File->FileName) + 10);
if (gCwd == NULL) {
return EFI_INVALID_PARAMETER;
}