X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;ds=sidebyside;f=EmbeddedPkg%2FLibrary%2FEfiFileLib%2FEfiFileLib.c;h=d3d959641346081e669b2aadcf7e128c707ff67a;hb=875c883ef36919045a56f2f7afff84fc8a115c59;hp=c58d21e8200e06a2386a0ffc142564b5faf3dd2f;hpb=16ccac42cff45475b04dc6a06a24d569baedb427;p=mirror_edk2.git diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c index c58d21e820..d3d9596413 100644 --- a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c +++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c @@ -57,6 +57,7 @@ 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 @@ -525,10 +526,27 @@ EblFvFileDevicePath ( 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 { @@ -542,14 +560,13 @@ EblFvFileDevicePath ( &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, @@ -574,26 +591,30 @@ EblFvFileDevicePath ( 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; } @@ -639,12 +660,13 @@ EfiOpen ( 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) { @@ -659,53 +681,54 @@ EfiOpen ( } } - 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); } @@ -715,7 +738,7 @@ EfiOpen ( File->FileName = &File->DeviceName[FileStart]; if (File->FileName[0] == '\0') { // if it is just a file name use / as root - File->FileName = "/"; + File->FileName = "\\"; } // @@ -744,7 +767,19 @@ EfiOpen ( // 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 @@ -879,14 +914,14 @@ EfiCopyFile ( 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; @@ -1045,7 +1080,8 @@ EfiClose ( } 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); } @@ -1162,8 +1198,8 @@ EfiSeek ( 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; } @@ -1289,12 +1325,6 @@ EfiRead ( } 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); @@ -1303,28 +1333,51 @@ EfiRead ( 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); @@ -1664,7 +1717,7 @@ EfiSetCwd ( // 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; }