316 lines
9.3 KiB
C
316 lines
9.3 KiB
C
/** @file
|
|
Simple code for H2O eMMC 5.0 FFU
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2014, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include <Uefi.h>
|
|
|
|
#include <Guid/FileInfo.h>
|
|
#include <Guid/H2OSdhcFfuImageGuid.h>
|
|
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/DebugLib.h>
|
|
|
|
#include <Protocol/FirmwareManagement.h>
|
|
#include <Protocol/SimpleFileSystem.h>
|
|
|
|
CHAR16 mFileName[] = L"fw.bin";
|
|
|
|
/**
|
|
Load the firmware named mFileName from Simple File System Protocol.
|
|
|
|
@param[out] FileData Firmware binary file
|
|
@param[out] FileSize File size
|
|
|
|
@retval EFI_SUCCESS Operation succeeded
|
|
@retval Other Operation failed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
LoadFwFileFromSimpleFileSystem (
|
|
OUT VOID **FileData,
|
|
OUT UINTN *FileSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *FileSystemHandles;
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
|
|
EFI_FILE_PROTOCOL *Root;
|
|
EFI_FILE_HANDLE File;
|
|
EFI_FILE_INFO *FileInfo;
|
|
UINTN FileInfoSize;
|
|
UINTN NumberFileSystemHandles;
|
|
UINTN Index;
|
|
|
|
NumberFileSystemHandles = 0;
|
|
FileSystemHandles = NULL;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
NULL,
|
|
&NumberFileSystemHandles,
|
|
&FileSystemHandles
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Root = NULL;
|
|
File = NULL;
|
|
FileInfo = NULL;
|
|
for (Index = 0; Index < NumberFileSystemHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
FileSystemHandles[Index],
|
|
&gEfiSimpleFileSystemProtocolGuid,
|
|
(VOID **) &SimpleFileSystem
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = SimpleFileSystem->OpenVolume (SimpleFileSystem, &Root);
|
|
if (EFI_ERROR(Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = Root->Open (
|
|
Root,
|
|
&File,
|
|
mFileName,
|
|
EFI_FILE_MODE_READ,
|
|
0
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
Root->Close(Root);
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NumberFileSystemHandles != 0) {
|
|
FreePool(FileSystemHandles);
|
|
}
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = File->GetInfo (
|
|
File,
|
|
&gEfiFileInfoGuid,
|
|
&FileInfoSize,
|
|
FileInfo
|
|
);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
FreePool (FileInfo);
|
|
FileInfo = AllocatePool (FileInfoSize);
|
|
if (FileInfo == NULL) {
|
|
Root->Close(Root);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Status = File->GetInfo (
|
|
File,
|
|
&gEfiFileInfoGuid,
|
|
&FileInfoSize,
|
|
FileInfo
|
|
);
|
|
}
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
File->Close(File);
|
|
Root->Close(Root);
|
|
return Status;
|
|
}
|
|
|
|
*FileSize = (UINTN)FileInfo->FileSize;
|
|
FreePool (FileInfo);
|
|
|
|
*FileData = AllocatePool (*FileSize);
|
|
|
|
if (*FileData != NULL) {
|
|
Status = File->Read (File, FileSize, *FileData);
|
|
if (EFI_ERROR(Status)) {
|
|
FreePool(*FileData);
|
|
}
|
|
}
|
|
|
|
File->Close(File);
|
|
Root->Close(Root);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Perform FFU process.
|
|
|
|
@param[in] ImageHandle EFI_HANDLE
|
|
@param[in] SystemTable EFI_SYSTEM_TABLE
|
|
|
|
@retval EFI_SUCCESS Operation succeeded
|
|
@retval Other Operation failed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
FfuDriverEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *FirmwareManagement;
|
|
EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress;
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
|
|
CHAR16 *AbortReason;
|
|
CHAR16 *PackageVersionName;
|
|
UINTN DescriptorSize;
|
|
UINTN ImageInfoSize;
|
|
UINT32 FmpImageInfoDescriptorVer;
|
|
UINT32 PackageVersion;
|
|
UINT32 ImageUpdatable;
|
|
UINT32 VendorCode;
|
|
UINT8 FmpImageInfoCount;
|
|
VOID *FileData;
|
|
UINTN FileSize;
|
|
UINTN HandleCount;
|
|
UINTN Index;
|
|
BOOLEAN Found;
|
|
|
|
HandleCount = 0;
|
|
HandleBuffer = NULL;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareManagementProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
Found = FALSE;
|
|
FirmwareManagement = NULL;
|
|
for (Index = 0; Index < HandleCount && !Found; Index++) {
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiFirmwareManagementProtocolGuid, (VOID *) &FirmwareManagement);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
ImageInfoSize = 0;
|
|
Status = FirmwareManagement->GetImageInfo (
|
|
FirmwareManagement,
|
|
&ImageInfoSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (Status != EFI_BUFFER_TOO_SMALL) {
|
|
continue;
|
|
}
|
|
|
|
FmpImageInfoBuf = NULL;
|
|
FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
|
|
if (FmpImageInfoBuf == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
PackageVersionName = NULL;
|
|
Status = FirmwareManagement->GetImageInfo (
|
|
FirmwareManagement,
|
|
&ImageInfoSize, // ImageInfoSize
|
|
FmpImageInfoBuf, // ImageInfo
|
|
&FmpImageInfoDescriptorVer, // DescriptorVersion
|
|
&FmpImageInfoCount, // DescriptorCount
|
|
&DescriptorSize, // DescriptorSize
|
|
&PackageVersion, // PackageVersion
|
|
&PackageVersionName // PackageVersionName
|
|
);
|
|
|
|
//
|
|
// If FMP GetInformation interface failed, skip this resource
|
|
//
|
|
if (EFI_ERROR(Status)) {
|
|
FreePool(FmpImageInfoBuf);
|
|
continue;
|
|
}
|
|
|
|
if (PackageVersionName != NULL) {
|
|
FreePool(PackageVersionName);
|
|
}
|
|
|
|
//
|
|
// Find the instance of FMP that distributed by SDHCD
|
|
//
|
|
if (CompareGuid(&FmpImageInfoBuf->ImageTypeId, &gH2OSdhcFfuImageGuid)) {
|
|
Found = TRUE;
|
|
}
|
|
|
|
FreePool(FmpImageInfoBuf);
|
|
}
|
|
|
|
if (!Found) {
|
|
Status = EFI_NOT_FOUND;
|
|
goto Exit;
|
|
}
|
|
|
|
Status = LoadFwFileFromSimpleFileSystem ((VOID **) &FileData, &FileSize);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Exit;
|
|
}
|
|
|
|
Status = FirmwareManagement->CheckImage (
|
|
FirmwareManagement,
|
|
1,
|
|
FileData,
|
|
FileSize,
|
|
&ImageUpdatable
|
|
);
|
|
if (EFI_ERROR(Status) || ImageUpdatable != IMAGE_UPDATABLE_VALID) {
|
|
goto Exit;
|
|
}
|
|
|
|
Progress = 0;
|
|
AbortReason = NULL;
|
|
Status = FirmwareManagement->SetImage (
|
|
FirmwareManagement,
|
|
1,
|
|
FileData,
|
|
FileSize,
|
|
&VendorCode,
|
|
Progress,
|
|
&AbortReason
|
|
);
|
|
if (AbortReason != NULL) {
|
|
DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));
|
|
FreePool(AbortReason);
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (HandleCount != 0) {
|
|
FreePool(HandleBuffer);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|