mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
OvmfPkg/RiscVVirt: Add support for Capsule Firmware Upgrade
This patch introduces support for firmware upgrades using the FMP capsule update mechanism. Signed-off-by: Tuan Phan <tphan@ventanamicro.com>
This commit is contained in:
parent
26c80e55ed
commit
5925977a4e
13 changed files with 1783 additions and 1 deletions
|
|
@ -54,7 +54,8 @@
|
|||
"ShellPkg/ShellPkg.dec",
|
||||
"EmbeddedPkg/EmbeddedPkg.dec",
|
||||
"SourceLevelDebugPkg/SourceLevelDebugPkg.dec",
|
||||
"StandaloneMmPkg/StandaloneMmPkg.dec"
|
||||
"StandaloneMmPkg/StandaloneMmPkg.dec",
|
||||
"FmpDevicePkg/FmpDevicePkg.dec"
|
||||
],
|
||||
# For host based unit tests
|
||||
"AcceptableDependencies-HOST_APPLICATION":[
|
||||
|
|
|
|||
332
OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py
Normal file
332
OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
## @file
|
||||
# Generate capsules for RiscVVirt platform
|
||||
# openssl, gcab must be install and in path
|
||||
#
|
||||
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
||||
'''
|
||||
GenCapsuleAll
|
||||
'''
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import subprocess
|
||||
import glob
|
||||
import shutil
|
||||
import struct
|
||||
import datetime
|
||||
|
||||
#
|
||||
# Globals for help information
|
||||
#
|
||||
__prog__ = 'GenCapsuleAll'
|
||||
__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.'
|
||||
__description__ = 'Generate RiscVVirt capsules.\n'
|
||||
|
||||
#
|
||||
# Globals
|
||||
#
|
||||
gWorkspace = ''
|
||||
gBaseToolsPath = ''
|
||||
gArgs = None
|
||||
|
||||
def LogAlways(Message):
|
||||
sys.stdout.write (__prog__ + ': ' + Message + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
def Log(Message):
|
||||
global gArgs
|
||||
if not gArgs.Verbose:
|
||||
return
|
||||
sys.stdout.write (__prog__ + ': ' + Message + '\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
def Error(Message, ExitValue=1):
|
||||
sys.stderr.write (__prog__ + ': ERROR: ' + Message + '\n')
|
||||
sys.exit (ExitValue)
|
||||
|
||||
def RelativePath(target):
|
||||
global gWorkspace
|
||||
Log('RelativePath' + target)
|
||||
return os.path.relpath (target, gWorkspace)
|
||||
|
||||
def NormalizePath(target):
|
||||
if isinstance(target, tuple):
|
||||
return os.path.normpath (os.path.join (*target))
|
||||
else:
|
||||
return os.path.normpath (target)
|
||||
|
||||
def RemoveFile(target):
|
||||
target = NormalizePath(target)
|
||||
if not target or target == os.pathsep:
|
||||
Error ('RemoveFile() invalid target')
|
||||
if os.path.exists(target):
|
||||
os.remove (target)
|
||||
Log ('remove %s' % (RelativePath (target)))
|
||||
|
||||
def RemoveDirectory(target):
|
||||
target = NormalizePath(target)
|
||||
if not target or target == os.pathsep:
|
||||
Error ('RemoveDirectory() invalid target')
|
||||
if os.path.exists(target):
|
||||
Log ('rmdir %s' % (RelativePath (target)))
|
||||
shutil.rmtree(target)
|
||||
|
||||
def CreateDirectory(target):
|
||||
target = NormalizePath(target)
|
||||
if not os.path.exists(target):
|
||||
Log ('mkdir %s' % (RelativePath (target)))
|
||||
os.makedirs (target)
|
||||
|
||||
def Copy(src, dst):
|
||||
src = NormalizePath(src)
|
||||
dst = NormalizePath(dst)
|
||||
for File in glob.glob(src):
|
||||
Log ('copy %s -> %s' % (RelativePath (File), RelativePath (dst)))
|
||||
shutil.copy (File, dst)
|
||||
|
||||
GenerateCapsuleCommand = '''
|
||||
GenerateCapsule
|
||||
--encode
|
||||
--guid {FMP_CAPSULE_GUID}
|
||||
--fw-version {FMP_CAPSULE_VERSION}
|
||||
--lsv {FMP_CAPSULE_LSV}
|
||||
--signer-private-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestCert.pem
|
||||
--other-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestSub.pub.pem
|
||||
--trusted-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestRoot.pub.pem
|
||||
-o {FMP_CAPSULE_FILE}
|
||||
{FMP_CAPSULE_PAYLOAD}
|
||||
'''
|
||||
MetaInfoXmlTemplate = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="firmware">
|
||||
<id>com.intel.FMP_CAPSULE_BASE_NAME.firmware</id>
|
||||
<name>FMP_CAPSULE_BASE_NAME</name>
|
||||
<summary>System firmware for the FMP_CAPSULE_BASE_NAME</summary>
|
||||
<description>
|
||||
Description of System firmware for the FMP_CAPSULE_BASE_NAME
|
||||
</description>
|
||||
<provides>
|
||||
<firmware type="flashed">FMP_CAPSULE_GUID</firmware>
|
||||
</provides>
|
||||
<url type="homepage">http://www.tianocore.org</url>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>BSD</project_license>
|
||||
<developer_name>Tianocore</developer_name>
|
||||
<releases>
|
||||
<release version="FMP_CAPSULE_VERSION_DECIMAL" date="FMP_CAPSULE_DATE">
|
||||
<description>
|
||||
Build FMP_CAPSULE_STRING
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
<!-- most OEMs do not need to do this... -->
|
||||
<custom>
|
||||
<value key="LVFS::InhibitDownload"/>
|
||||
</custom>
|
||||
</component>
|
||||
'''
|
||||
|
||||
def GenCapsuleDevice (BaseName, PayloadFileName, Guid, Version, Lsv, CapsulesPath, CapsulesSubDir):
|
||||
global gBaseToolsPath
|
||||
LogAlways ('Generate Capsule: {0} {1:08x} {2:08x} {3}'.format (Guid, Version, Lsv, PayloadFileName))
|
||||
|
||||
VersionString = '.'.join([str(ord(x)) for x in struct.pack('>I', Version).decode()])
|
||||
|
||||
FmpCapsuleFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cap'))
|
||||
Command = GenerateCapsuleCommand.format (
|
||||
FMP_CAPSULE_GUID = Guid,
|
||||
FMP_CAPSULE_VERSION = Version,
|
||||
FMP_CAPSULE_LSV = Lsv,
|
||||
BASE_TOOLS_PATH = gBaseToolsPath,
|
||||
FMP_CAPSULE_FILE = FmpCapsuleFile,
|
||||
FMP_CAPSULE_PAYLOAD = PayloadFileName
|
||||
)
|
||||
Command = ' '.join(Command.splitlines()).strip()
|
||||
if gArgs.Verbose:
|
||||
Command = Command + ' -v'
|
||||
|
||||
Log (Command)
|
||||
|
||||
Process = subprocess.Popen(Command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
ProcessOutput = Process.communicate()
|
||||
|
||||
if Process.returncode == 0:
|
||||
Log (ProcessOutput[0].decode())
|
||||
else:
|
||||
LogAlways (Command)
|
||||
LogAlways (ProcessOutput[0].decode())
|
||||
Error ('GenerateCapsule returned an error')
|
||||
|
||||
Copy (PayloadFileName, (CapsulesPath, 'firmware.bin'))
|
||||
MetaInfoXml = MetaInfoXmlTemplate
|
||||
MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_GUID', Guid)
|
||||
MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_BASE_NAME', BaseName)
|
||||
MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_VERSION_DECIMAL', str(Version))
|
||||
MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_STRING', VersionString)
|
||||
MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_DATE', str(datetime.date.today()))
|
||||
f = open (NormalizePath ((CapsulesPath, 'firmware.metainfo.xml')), 'w')
|
||||
f.write(MetaInfoXml)
|
||||
f.close()
|
||||
|
||||
Command = 'gcab --create firmware.cab firmware.bin firmware.metainfo.xml'
|
||||
Log (Command)
|
||||
|
||||
Process = subprocess.Popen(Command, cwd=CapsulesPath, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
ProcessOutput = Process.communicate()
|
||||
|
||||
if Process.returncode == 0:
|
||||
Log (ProcessOutput[0].decode())
|
||||
else:
|
||||
LogAlways (Command)
|
||||
LogAlways (ProcessOutput[0].decode())
|
||||
Error ('GenerateCapsule returned an error')
|
||||
|
||||
FmpCabinetFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cab'))
|
||||
|
||||
Copy ((CapsulesPath, 'firmware.cab'), FmpCabinetFile)
|
||||
|
||||
RemoveFile ((CapsulesPath, 'firmware.cab'))
|
||||
RemoveFile ((CapsulesPath, 'firmware.metainfo.xml'))
|
||||
RemoveFile ((CapsulesPath, 'firmware.bin'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
#
|
||||
# Create command line argument parser object
|
||||
#
|
||||
parser = argparse.ArgumentParser (
|
||||
prog = __prog__,
|
||||
description = __description__ + __copyright__,
|
||||
conflict_handler = 'resolve'
|
||||
)
|
||||
parser.add_argument (
|
||||
'-a', '--arch', dest = 'Arch', nargs = '+', action = 'append',
|
||||
required = True,
|
||||
help = '''ARCHS is one of list: IA32, X64, IPF, ARM, AARCH64, RISCV64
|
||||
or EBC, which overrides target.txt's TARGET_ARCH definition.
|
||||
To specify more archs, please repeat this option.'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'-t', '--tagname', dest = 'ToolChain', required = True,
|
||||
help = '''Using the Tool Chain Tagname to build the platform,
|
||||
overriding target.txt's TOOL_CHAIN_TAG definition.'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'-p', '--platform', dest = 'PlatformFile', required = True,
|
||||
help = '''Build the platform specified by the DSC file name argument,
|
||||
overriding target.txt's ACTIVE_PLATFORM definition.'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'-b', '--buildtarget', dest = 'BuildTarget', required = True,
|
||||
help = '''Using the TARGET to build the platform, overriding
|
||||
target.txt's TARGET definition.'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'--conf=', dest = 'ConfDirectory', required = True,
|
||||
help = '''Specify the customized Conf directory.'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'-D', '--define', dest = 'Define', nargs='*', action = 'append',
|
||||
help = '''Macro: "Name [= Value]".'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'-v', '--verbose', dest = 'Verbose', action = 'store_true',
|
||||
help = '''Turn on verbose output with informational messages printed'''
|
||||
)
|
||||
parser.add_argument (
|
||||
'--package', dest = 'Package', nargs = '*', action = 'append',
|
||||
help = '''The directory name of a package of tests to copy'''
|
||||
)
|
||||
|
||||
#
|
||||
# Parse command line arguments
|
||||
#
|
||||
gArgs, remaining = parser.parse_known_args()
|
||||
gArgs.BuildType = 'all'
|
||||
for BuildType in ['all', 'fds', 'genc', 'genmake', 'clean', 'cleanall', 'modules', 'libraries', 'run']:
|
||||
if BuildType in remaining:
|
||||
gArgs.BuildType = BuildType
|
||||
remaining.remove(BuildType)
|
||||
break
|
||||
gArgs.Remaining = ' '.join(remaining)
|
||||
|
||||
#
|
||||
# Get WORKSPACE environment variable
|
||||
#
|
||||
try:
|
||||
gWorkspace = os.environ['WORKSPACE']
|
||||
except:
|
||||
Error ('WORKSPACE environment variable not set')
|
||||
|
||||
#
|
||||
# Get PACKAGES_PATH and generate prioritized list of paths
|
||||
#
|
||||
PathList = [gWorkspace]
|
||||
try:
|
||||
PathList += os.environ['PACKAGES_PATH'].split(os.pathsep)
|
||||
except:
|
||||
pass
|
||||
|
||||
#
|
||||
# Determine full path to BaseTools
|
||||
#
|
||||
for Path in PathList:
|
||||
if os.path.exists (os.path.join (Path, 'BaseTools')):
|
||||
gBaseToolsPath = os.path.join (Path, 'BaseTools')
|
||||
break
|
||||
|
||||
#
|
||||
# Parse PLATFORM_NAME from DSC file
|
||||
#
|
||||
for Path in PathList:
|
||||
if os.path.exists (os.path.join (Path, gArgs.PlatformFile)):
|
||||
Dsc = open (os.path.join (Path, gArgs.PlatformFile), 'r').readlines()
|
||||
break
|
||||
for Line in Dsc:
|
||||
if Line.strip().startswith('PLATFORM_NAME'):
|
||||
OutputDirectory = os.path.join ('Build', Line.strip().split('=')[1].strip())
|
||||
break
|
||||
|
||||
#
|
||||
# Determine full paths to EDK II build directory, EDK II build output
|
||||
# directory and the CPU arch of the UEFI phase.
|
||||
#
|
||||
CommandDir = os.path.dirname(sys.argv[0])
|
||||
EdkiiBuildDir = os.path.join (gWorkspace, OutputDirectory)
|
||||
EdkiiBuildOutput = os.path.join (EdkiiBuildDir, gArgs.BuildTarget + '_' + gArgs.ToolChain)
|
||||
UefiArch = gArgs.Arch[0][0]
|
||||
if len (gArgs.Arch) > 1:
|
||||
if ['RISCV64'] in gArgs.Arch:
|
||||
UefiArch = 'RISCV64'
|
||||
|
||||
CapsulesPath = NormalizePath((EdkiiBuildDir, 'Capsules'))
|
||||
|
||||
CapsulesSubDir = 'TestCert' + '_' + UefiArch + '_' + gArgs.BuildTarget + '_' + gArgs.ToolChain
|
||||
|
||||
#
|
||||
# Create output directories
|
||||
#
|
||||
try:
|
||||
CreateDirectory ((CapsulesPath))
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
CreateDirectory ((CapsulesPath, CapsulesSubDir))
|
||||
except:
|
||||
pass
|
||||
|
||||
#
|
||||
# Copy CapsuleApp
|
||||
#
|
||||
Copy ((EdkiiBuildOutput, UefiArch, 'CapsuleApp.efi'), (CapsulesPath, CapsulesSubDir))
|
||||
|
||||
#
|
||||
# Generate capsules for RiscVVirt Firmware Updates
|
||||
#
|
||||
CodeFW = os.path.join (EdkiiBuildOutput, 'FV', 'RISCV_VIRT_CODE.fd')
|
||||
GenCapsuleDevice('RISCVVIRT', CodeFW,'bcbacac2-1d1d-4c14-89a3-5e27496b702d',0x00010000,0x00000000, CapsulesPath, CapsulesSubDir)
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/** @file
|
||||
Provides platform policy services used during a capsule update.
|
||||
|
||||
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Library/CapsuleUpdatePolicyLib.h>
|
||||
|
||||
/**
|
||||
Determine if the system power state supports a capsule update.
|
||||
|
||||
@param[out] Good Returns TRUE if system power state supports a capsule
|
||||
update. Returns FALSE if system power state does not
|
||||
support a capsule update. Return value is only valid if
|
||||
return status is EFI_SUCCESS.
|
||||
|
||||
@retval EFI_SUCCESS Good parameter has been updated with result.
|
||||
@retval EFI_INVALID_PARAMETER Good is NULL.
|
||||
@retval EFI_DEVICE_ERROR System power state can not be determined.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CheckSystemPower (
|
||||
OUT BOOLEAN *Good
|
||||
)
|
||||
{
|
||||
*Good = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the system thermal state supports a capsule update.
|
||||
|
||||
@param[out] Good Returns TRUE if system thermal state supports a capsule
|
||||
update. Returns FALSE if system thermal state does not
|
||||
support a capsule update. Return value is only valid if
|
||||
return status is EFI_SUCCESS.
|
||||
|
||||
@retval EFI_SUCCESS Good parameter has been updated with result.
|
||||
@retval EFI_INVALID_PARAMETER Good is NULL.
|
||||
@retval EFI_DEVICE_ERROR System thermal state can not be determined.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CheckSystemThermal (
|
||||
OUT BOOLEAN *Good
|
||||
)
|
||||
{
|
||||
*Good = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the system environment state supports a capsule update.
|
||||
|
||||
@param[out] Good Returns TRUE if system environment state supports a capsule
|
||||
update. Returns FALSE if system environment state does not
|
||||
support a capsule update. Return value is only valid if
|
||||
return status is EFI_SUCCESS.
|
||||
|
||||
@retval EFI_SUCCESS Good parameter has been updated with result.
|
||||
@retval EFI_INVALID_PARAMETER Good is NULL.
|
||||
@retval EFI_DEVICE_ERROR System environment state can not be determined.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CheckSystemEnvironment (
|
||||
OUT BOOLEAN *Good
|
||||
)
|
||||
{
|
||||
*Good = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the Lowest Supported Version checks should be performed. The
|
||||
expected result from this function is TRUE. A platform can choose to return
|
||||
FALSE (e.g. during manufacturing or servicing) to allow a capsule update to a
|
||||
version below the current Lowest Supported Version.
|
||||
|
||||
@retval TRUE The lowest supported version check is required.
|
||||
@retval FALSE Do not perform lowest support version check.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsLowestSupportedVersionCheckRequired (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the FMP device should be locked when the event specified by
|
||||
PcdFmpDeviceLockEventGuid is signaled. The expected result from this function
|
||||
is TRUE so the FMP device is always locked. A platform can choose to return
|
||||
FALSE (e.g. during manufacturing) to allow FMP devices to remain unlocked.
|
||||
|
||||
@retval TRUE The FMP device lock action is required at lock event guid.
|
||||
@retval FALSE Do not perform FMP device lock at lock event guid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsLockFmpDeviceAtLockEventGuidRequired (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Not lock FMP device for this platform
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
## @file
|
||||
# Provides platform policy services used during a capsule update.
|
||||
#
|
||||
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.30
|
||||
BASE_NAME = CapsuleUpdatePolicyLib
|
||||
MODULE_UNI_FILE = CapsuleUpdatePolicyLib.uni
|
||||
FILE_GUID = 3ed188f7-7aba-47ff-bdeb-2ac23287a5ea
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = CapsuleUpdatePolicyLib
|
||||
|
||||
#
|
||||
# VALID_ARCHITECTURES = RISCV64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
CapsuleUpdatePolicyLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
FmpDevicePkg/FmpDevicePkg.dec
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// /** @file
|
||||
// Provides platform policy services used during a capsule update.
|
||||
//
|
||||
// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Provides platform policy services used during a capsule update."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "Provides platform policy services used during a capsule update."
|
||||
|
|
@ -0,0 +1,774 @@
|
|||
/** @file
|
||||
Provides firmware device specific services to support updates of a firmware
|
||||
image stored in a firmware device.
|
||||
|
||||
Copyright (c) Microsoft Corporation.<BR>
|
||||
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Guid/SystemResourceTable.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/FmpDeviceLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Include/LastAttemptStatus.h>
|
||||
#include "../PlatformFlashAccessLib/PlatformFlashAccessLib.h"
|
||||
|
||||
#define __BUILD_STRING(x) L ## #x
|
||||
#define BUILD_STRING(x) L"build #" __BUILD_STRING(x)
|
||||
#define CURRENT_FIRMWARE_VERSION FixedPcdGet32 (PcdFirmwareRevision)
|
||||
#define CURRENT_FIRMWARE_VERSION_STRING BUILD_STRING (CURRENT_FIRMWARE_VERSION)
|
||||
|
||||
typedef struct {
|
||||
PLATFORM_FIRMWARE_TYPE FirmwareType;
|
||||
FLASH_ADDRESS_TYPE AddressType;
|
||||
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||
UINTN Length;
|
||||
UINTN ImageOffset;
|
||||
} UPDATE_CONFIG_DATA;
|
||||
|
||||
UPDATE_CONFIG_DATA mUpdateConfigData[] = {
|
||||
{ PlatformFirmwareTypeSystemFirmware, FlashAddressTypeAbsoluteAddress, 0x20000000, 0x00800000, 0x00000000 },
|
||||
};
|
||||
|
||||
/**
|
||||
Provide a function to install the Firmware Management Protocol instance onto a
|
||||
device handle when the device is managed by a driver that follows the UEFI
|
||||
Driver Model. If the device is not managed by a driver that follows the UEFI
|
||||
Driver Model, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] FmpInstaller Function that installs the Firmware Management
|
||||
Protocol.
|
||||
|
||||
@retval EFI_SUCCESS The device is managed by a driver that follows the
|
||||
UEFI Driver Model. FmpInstaller must be called on
|
||||
each Driver Binding Start().
|
||||
@retval EFI_UNSUPPORTED The device is not managed by a driver that follows
|
||||
the UEFI Driver Model.
|
||||
@retval other The Firmware Management Protocol for this firmware
|
||||
device is not installed. The firmware device is
|
||||
still locked using FmpDeviceLock().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RegisterFmpInstaller (
|
||||
IN FMP_DEVICE_LIB_REGISTER_FMP_INSTALLER Function
|
||||
)
|
||||
{
|
||||
//
|
||||
// This is a system firmware update that does not use Driver Binding Protocol
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Provide a function to uninstall the Firmware Management Protocol instance from a
|
||||
device handle when the device is managed by a driver that follows the UEFI
|
||||
Driver Model. If the device is not managed by a driver that follows the UEFI
|
||||
Driver Model, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] FmpUninstaller Function that installs the Firmware Management
|
||||
Protocol.
|
||||
|
||||
@retval EFI_SUCCESS The device is managed by a driver that follows the
|
||||
UEFI Driver Model. FmpUninstaller must be called on
|
||||
each Driver Binding Stop().
|
||||
@retval EFI_UNSUPPORTED The device is not managed by a driver that follows
|
||||
the UEFI Driver Model.
|
||||
@retval other The Firmware Management Protocol for this firmware
|
||||
device is not installed. The firmware device is
|
||||
still locked using FmpDeviceLock().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RegisterFmpUninstaller (
|
||||
IN FMP_DEVICE_LIB_REGISTER_FMP_UNINSTALLER Function
|
||||
)
|
||||
{
|
||||
//
|
||||
// This is a system firmware update that does not use Driver Binding Protocol
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the device context for the FmpDeviceLib services when the device is
|
||||
managed by a driver that follows the UEFI Driver Model. If the device is not
|
||||
managed by a driver that follows the UEFI Driver Model, then EFI_UNSUPPORTED
|
||||
is returned. Once a device context is set, the FmpDeviceLib services
|
||||
operate on the currently set device context.
|
||||
|
||||
@param[in] Handle Device handle for the FmpDeviceLib services.
|
||||
If Handle is NULL, then Context is freed.
|
||||
@param[in, out] Context Device context for the FmpDeviceLib services.
|
||||
If Context is NULL, then a new context is allocated
|
||||
for Handle and the current device context is set and
|
||||
returned in Context. If Context is not NULL, then
|
||||
the current device context is set.
|
||||
|
||||
@retval EFI_SUCCESS The device is managed by a driver that follows the
|
||||
UEFI Driver Model.
|
||||
@retval EFI_UNSUPPORTED The device is not managed by a driver that follows
|
||||
the UEFI Driver Model.
|
||||
@retval other The Firmware Management Protocol for this firmware
|
||||
device is not installed. The firmware device is
|
||||
still locked using FmpDeviceLock().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceSetContext (
|
||||
IN EFI_HANDLE Handle,
|
||||
IN OUT VOID **Context
|
||||
)
|
||||
{
|
||||
//
|
||||
// This is a system firmware update that does not use Driver Binding Protocol
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the size, in bytes, of the firmware image currently stored in the
|
||||
firmware device. This function is used to by the GetImage() and
|
||||
GetImageInfo() services of the Firmware Management Protocol. If the image
|
||||
size can not be determined from the firmware device, then 0 must be returned.
|
||||
|
||||
@param[out] Size Pointer to the size, in bytes, of the firmware image
|
||||
currently stored in the firmware device.
|
||||
|
||||
@retval EFI_SUCCESS The size of the firmware image currently
|
||||
stored in the firmware device was returned.
|
||||
@retval EFI_INVALID_PARAMETER Size is NULL.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support reporting
|
||||
the size of the currently stored firmware image.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to determine the
|
||||
size of the firmware image currently stored in
|
||||
in the firmware device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetSize (
|
||||
OUT UINTN *Size
|
||||
)
|
||||
{
|
||||
if (Size == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the GUID value used to fill in the ImageTypeId field of the
|
||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
||||
service of the Firmware Management Protocol. If EFI_UNSUPPORTED is returned,
|
||||
then the ImageTypeId field is set to gEfiCallerIdGuid. If EFI_SUCCESS is
|
||||
returned, then ImageTypeId is set to the Guid returned from this function.
|
||||
|
||||
@param[out] Guid Double pointer to a GUID value that is updated to point to
|
||||
to a GUID value. The GUID value is not allocated and must
|
||||
not be modified or freed by the caller.
|
||||
|
||||
@retval EFI_SUCCESS EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set
|
||||
to the returned Guid value.
|
||||
@retval EFI_UNSUPPORTED EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set
|
||||
to gEfiCallerIdGuid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetImageTypeIdGuidPtr (
|
||||
OUT EFI_GUID **Guid
|
||||
)
|
||||
{
|
||||
*Guid = &gEfiCallerIdGuid;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns values used to fill in the AttributesSupported and AttributesSettings
|
||||
fields of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the
|
||||
GetImageInfo() service of the Firmware Management Protocol. The following
|
||||
bit values from the Firmware Management Protocol may be combined:
|
||||
IMAGE_ATTRIBUTE_IMAGE_UPDATABLE
|
||||
IMAGE_ATTRIBUTE_RESET_REQUIRED
|
||||
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED
|
||||
IMAGE_ATTRIBUTE_IN_USE
|
||||
IMAGE_ATTRIBUTE_UEFI_IMAGE
|
||||
|
||||
@param[out] Supported Attributes supported by this firmware device.
|
||||
@param[out] Setting Attributes settings for this firmware device.
|
||||
|
||||
@retval EFI_SUCCESS The attributes supported by the firmware
|
||||
device were returned.
|
||||
@retval EFI_INVALID_PARAMETER Supported is NULL.
|
||||
@retval EFI_INVALID_PARAMETER Setting is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetAttributes (
|
||||
OUT UINT64 *Supported,
|
||||
OUT UINT64 *Setting
|
||||
)
|
||||
{
|
||||
if ((Supported == NULL) || (Setting == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*Supported = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
|
||||
IMAGE_ATTRIBUTE_RESET_REQUIRED |
|
||||
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
|
||||
IMAGE_ATTRIBUTE_IN_USE
|
||||
);
|
||||
*Setting = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
|
||||
IMAGE_ATTRIBUTE_RESET_REQUIRED |
|
||||
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
|
||||
IMAGE_ATTRIBUTE_IN_USE
|
||||
);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value used to fill in the LowestSupportedVersion field of the
|
||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
||||
service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then
|
||||
the firmware device supports a method to report the LowestSupportedVersion
|
||||
value from the currently stored firmware image. If the value can not be
|
||||
reported for the firmware image currently stored in the firmware device, then
|
||||
EFI_UNSUPPORTED must be returned. EFI_DEVICE_ERROR is returned if an error
|
||||
occurs attempting to retrieve the LowestSupportedVersion value for the
|
||||
currently stored firmware image.
|
||||
|
||||
@note It is recommended that all firmware devices support a method to report
|
||||
the LowestSupportedVersion value from the currently stored firmware
|
||||
image.
|
||||
|
||||
@param[out] LowestSupportedVersion LowestSupportedVersion value retrieved
|
||||
from the currently stored firmware image.
|
||||
|
||||
@retval EFI_SUCCESS The lowest supported version of currently stored
|
||||
firmware image was returned in LowestSupportedVersion.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support a method to
|
||||
report the lowest supported version of the currently
|
||||
stored firmware image.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the lowest
|
||||
supported version of the currently stored firmware
|
||||
image.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetLowestSupportedVersion (
|
||||
OUT UINT32 *LowestSupportedVersion
|
||||
)
|
||||
{
|
||||
*LowestSupportedVersion = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the Null-terminated Unicode string that is used to fill in the
|
||||
VersionName field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is
|
||||
returned by the GetImageInfo() service of the Firmware Management Protocol.
|
||||
The returned string must be allocated using EFI_BOOT_SERVICES.AllocatePool().
|
||||
|
||||
@note It is recommended that all firmware devices support a method to report
|
||||
the VersionName string from the currently stored firmware image.
|
||||
|
||||
@param[out] VersionString The version string retrieved from the currently
|
||||
stored firmware image.
|
||||
|
||||
@retval EFI_SUCCESS The version string of currently stored
|
||||
firmware image was returned in Version.
|
||||
@retval EFI_INVALID_PARAMETER VersionString is NULL.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support a method
|
||||
to report the version string of the currently
|
||||
stored firmware image.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the
|
||||
version string of the currently stored
|
||||
firmware image.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the
|
||||
buffer for the version string of the currently
|
||||
stored firmware image.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetVersionString (
|
||||
OUT CHAR16 **VersionString
|
||||
)
|
||||
{
|
||||
if (VersionString == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*VersionString = (CHAR16 *)AllocateCopyPool (
|
||||
sizeof (CURRENT_FIRMWARE_VERSION_STRING),
|
||||
CURRENT_FIRMWARE_VERSION_STRING
|
||||
);
|
||||
if (*VersionString == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value used to fill in the Version field of the
|
||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
||||
service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then
|
||||
the firmware device supports a method to report the Version value from the
|
||||
currently stored firmware image. If the value can not be reported for the
|
||||
firmware image currently stored in the firmware device, then EFI_UNSUPPORTED
|
||||
must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting
|
||||
to retrieve the LowestSupportedVersion value for the currently stored firmware
|
||||
image.
|
||||
|
||||
@note It is recommended that all firmware devices support a method to report
|
||||
the Version value from the currently stored firmware image.
|
||||
|
||||
@param[out] Version The version value retrieved from the currently stored
|
||||
firmware image.
|
||||
|
||||
@retval EFI_SUCCESS The version of currently stored firmware image was
|
||||
returned in Version.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support a method to
|
||||
report the version of the currently stored firmware
|
||||
image.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the version
|
||||
of the currently stored firmware image.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetVersion (
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
*Version = PcdGet32 (PcdFirmwareRevision);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the value used to fill in the HardwareInstance field of the
|
||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()
|
||||
service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then
|
||||
the firmware device supports a method to report the HardwareInstance value.
|
||||
If the value can not be reported for the firmware device, then EFI_UNSUPPORTED
|
||||
must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting
|
||||
to retrieve the HardwareInstance value for the firmware device.
|
||||
|
||||
@param[out] HardwareInstance The hardware instance value for the firmware
|
||||
device.
|
||||
|
||||
@retval EFI_SUCCESS The hardware instance for the current firmware
|
||||
device is returned in HardwareInstance.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support a method to
|
||||
report the hardware instance value.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the hardware
|
||||
instance value.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetHardwareInstance (
|
||||
OUT UINT64 *HardwareInstance
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a copy of the firmware image currently stored in the firmware device.
|
||||
|
||||
@note It is recommended that all firmware devices support a method to retrieve
|
||||
a copy currently stored firmware image. This can be used to support
|
||||
features such as recovery and rollback.
|
||||
|
||||
@param[out] Image Pointer to a caller allocated buffer where the
|
||||
currently stored firmware image is copied to.
|
||||
@param[in, out] ImageSize Pointer the size, in bytes, of the Image buffer.
|
||||
On return, points to the size, in bytes, of firmware
|
||||
image currently stored in the firmware device.
|
||||
|
||||
@retval EFI_SUCCESS Image contains a copy of the firmware image
|
||||
currently stored in the firmware device, and
|
||||
ImageSize contains the size, in bytes, of the
|
||||
firmware image currently stored in the
|
||||
firmware device.
|
||||
@retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small
|
||||
to hold the firmware image currently stored in
|
||||
the firmware device. The buffer size required
|
||||
is returned in ImageSize.
|
||||
@retval EFI_INVALID_PARAMETER The Image is NULL.
|
||||
@retval EFI_INVALID_PARAMETER The ImageSize is NULL.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported.
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the
|
||||
firmware image currently stored in the firmware
|
||||
device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceGetImage (
|
||||
OUT VOID *Image,
|
||||
IN OUT UINTN *ImageSize
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if a new firmware image is valid for the firmware device. This
|
||||
function allows firmware update operation to validate the firmware image
|
||||
before FmpDeviceSetImage() is called.
|
||||
|
||||
@param[in] Image Points to a new firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of a new firmware image.
|
||||
@param[out] ImageUpdatable Indicates if a new firmware image is valid for
|
||||
a firmware update to the firmware device. The
|
||||
following values from the Firmware Management
|
||||
Protocol are supported:
|
||||
IMAGE_UPDATABLE_VALID
|
||||
IMAGE_UPDATABLE_INVALID
|
||||
IMAGE_UPDATABLE_INVALID_TYPE
|
||||
IMAGE_UPDATABLE_INVALID_OLD
|
||||
IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
|
||||
|
||||
@retval EFI_SUCCESS The image was successfully checked. Additional
|
||||
status information is returned in
|
||||
ImageUpdatable.
|
||||
@retval EFI_INVALID_PARAMETER Image is NULL.
|
||||
@retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceCheckImage (
|
||||
IN CONST VOID *Image,
|
||||
IN UINTN ImageSize,
|
||||
OUT UINT32 *ImageUpdatable
|
||||
)
|
||||
{
|
||||
UINT32 LastAttemptStatus;
|
||||
|
||||
return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdatable, &LastAttemptStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if a new firmware image is valid for the firmware device. This
|
||||
function allows firmware update operation to validate the firmware image
|
||||
before FmpDeviceSetImage() is called.
|
||||
|
||||
@param[in] Image Points to a new firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of a new firmware image.
|
||||
@param[out] ImageUpdatable Indicates if a new firmware image is valid for
|
||||
a firmware update to the firmware device. The
|
||||
following values from the Firmware Management
|
||||
Protocol are supported:
|
||||
IMAGE_UPDATABLE_VALID
|
||||
IMAGE_UPDATABLE_INVALID
|
||||
IMAGE_UPDATABLE_INVALID_TYPE
|
||||
IMAGE_UPDATABLE_INVALID_OLD
|
||||
IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE
|
||||
@param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt
|
||||
status to report back to the ESRT table in case
|
||||
of error.
|
||||
|
||||
The return status code must fall in the range of
|
||||
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
|
||||
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
|
||||
|
||||
If the value falls outside this range, it will be converted
|
||||
to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
|
||||
|
||||
@retval EFI_SUCCESS The image was successfully checked. Additional
|
||||
status information is returned in
|
||||
ImageUpdatable.
|
||||
@retval EFI_INVALID_PARAMETER Image is NULL.
|
||||
@retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceCheckImageWithStatus (
|
||||
IN CONST VOID *Image,
|
||||
IN UINTN ImageSize,
|
||||
OUT UINT32 *ImageUpdatable,
|
||||
OUT UINT32 *LastAttemptStatus
|
||||
)
|
||||
{
|
||||
if (LastAttemptStatus == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer Parameter is NULL.\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
|
||||
|
||||
if (ImageUpdatable == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Parameter is NULL.\n"));
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Set to valid and then if any tests fail it will update this flag.
|
||||
//
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_VALID;
|
||||
|
||||
if (Image == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter is NULL.\n"));
|
||||
//
|
||||
// Not sure if this is needed
|
||||
//
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Updates a firmware device with a new firmware image. This function returns
|
||||
EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
|
||||
is updatable, the function should perform the following minimal validations
|
||||
before proceeding to do the firmware image update.
|
||||
- Validate that the image is a supported image for this firmware device.
|
||||
Return EFI_ABORTED if the image is not supported. Additional details
|
||||
on why the image is not a supported image may be returned in AbortReason.
|
||||
- Validate the data from VendorCode if is not NULL. Firmware image
|
||||
validation must be performed before VendorCode data validation.
|
||||
VendorCode data is ignored or considered invalid if image validation
|
||||
fails. Return EFI_ABORTED if the VendorCode data is invalid.
|
||||
|
||||
VendorCode enables vendor to implement vendor-specific firmware image update
|
||||
policy. Null if the caller did not specify the policy or use the default
|
||||
policy. As an example, vendor can implement a policy to allow an option to
|
||||
force a firmware image update when the abort reason is due to the new firmware
|
||||
image version is older than the current firmware image version or bad image
|
||||
checksum. Sensitive operations such as those wiping the entire firmware image
|
||||
and render the device to be non-functional should be encoded in the image
|
||||
itself rather than passed with the VendorCode. AbortReason enables vendor to
|
||||
have the option to provide a more detailed description of the abort reason to
|
||||
the caller.
|
||||
|
||||
@param[in] Image Points to the new firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of the new firmware image.
|
||||
@param[in] VendorCode This enables vendor to implement vendor-specific
|
||||
firmware image update policy. NULL indicates
|
||||
the caller did not specify the policy or use the
|
||||
default policy.
|
||||
@param[in] Progress A function used to report the progress of
|
||||
updating the firmware device with the new
|
||||
firmware image.
|
||||
@param[in] CapsuleFwVersion The version of the new firmware image from the
|
||||
update capsule that provided the new firmware
|
||||
image.
|
||||
@param[out] AbortReason A pointer to a pointer to a Null-terminated
|
||||
Unicode string providing more details on an
|
||||
aborted operation. The buffer is allocated by
|
||||
this function with
|
||||
EFI_BOOT_SERVICES.AllocatePool(). It is the
|
||||
caller's responsibility to free this buffer with
|
||||
EFI_BOOT_SERVICES.FreePool().
|
||||
|
||||
@retval EFI_SUCCESS The firmware device was successfully updated
|
||||
with the new firmware image.
|
||||
@retval EFI_ABORTED The operation is aborted. Additional details
|
||||
are provided in AbortReason.
|
||||
@retval EFI_INVALID_PARAMETER The Image was NULL.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceSetImage (
|
||||
IN CONST VOID *Image,
|
||||
IN UINTN ImageSize,
|
||||
IN CONST VOID *VendorCode OPTIONAL,
|
||||
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL,
|
||||
IN UINT32 CapsuleFwVersion,
|
||||
OUT CHAR16 **AbortReason
|
||||
)
|
||||
{
|
||||
UINT32 LastAttemptStatus;
|
||||
|
||||
return FmpDeviceSetImageWithStatus (
|
||||
Image,
|
||||
ImageSize,
|
||||
VendorCode,
|
||||
Progress,
|
||||
CapsuleFwVersion,
|
||||
AbortReason,
|
||||
&LastAttemptStatus
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Updates a firmware device with a new firmware image. This function returns
|
||||
EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image
|
||||
is updatable, the function should perform the following minimal validations
|
||||
before proceeding to do the firmware image update.
|
||||
- Validate that the image is a supported image for this firmware device.
|
||||
Return EFI_ABORTED if the image is not supported. Additional details
|
||||
on why the image is not a supported image may be returned in AbortReason.
|
||||
- Validate the data from VendorCode if is not NULL. Firmware image
|
||||
validation must be performed before VendorCode data validation.
|
||||
VendorCode data is ignored or considered invalid if image validation
|
||||
fails. Return EFI_ABORTED if the VendorCode data is invalid.
|
||||
|
||||
VendorCode enables vendor to implement vendor-specific firmware image update
|
||||
policy. Null if the caller did not specify the policy or use the default
|
||||
policy. As an example, vendor can implement a policy to allow an option to
|
||||
force a firmware image update when the abort reason is due to the new firmware
|
||||
image version is older than the current firmware image version or bad image
|
||||
checksum. Sensitive operations such as those wiping the entire firmware image
|
||||
and render the device to be non-functional should be encoded in the image
|
||||
itself rather than passed with the VendorCode. AbortReason enables vendor to
|
||||
have the option to provide a more detailed description of the abort reason to
|
||||
the caller.
|
||||
|
||||
@param[in] Image Points to the new firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of the new firmware image.
|
||||
@param[in] VendorCode This enables vendor to implement vendor-specific
|
||||
firmware image update policy. NULL indicates
|
||||
the caller did not specify the policy or use the
|
||||
default policy.
|
||||
@param[in] Progress A function used to report the progress of
|
||||
updating the firmware device with the new
|
||||
firmware image.
|
||||
@param[in] CapsuleFwVersion The version of the new firmware image from the
|
||||
update capsule that provided the new firmware
|
||||
image.
|
||||
@param[out] AbortReason A pointer to a pointer to a Null-terminated
|
||||
Unicode string providing more details on an
|
||||
aborted operation. The buffer is allocated by
|
||||
this function with
|
||||
EFI_BOOT_SERVICES.AllocatePool(). It is the
|
||||
caller's responsibility to free this buffer with
|
||||
EFI_BOOT_SERVICES.FreePool().
|
||||
@param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt
|
||||
status to report back to the ESRT table in case
|
||||
of error. This value will only be checked when this
|
||||
function returns an error.
|
||||
|
||||
The return status code must fall in the range of
|
||||
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to
|
||||
LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE.
|
||||
|
||||
If the value falls outside this range, it will be converted
|
||||
to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.
|
||||
|
||||
@retval EFI_SUCCESS The firmware device was successfully updated
|
||||
with the new firmware image.
|
||||
@retval EFI_ABORTED The operation is aborted. Additional details
|
||||
are provided in AbortReason.
|
||||
@retval EFI_INVALID_PARAMETER The Image was NULL.
|
||||
@retval EFI_UNSUPPORTED The operation is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceSetImageWithStatus (
|
||||
IN CONST VOID *Image,
|
||||
IN UINTN ImageSize,
|
||||
IN CONST VOID *VendorCode OPTIONAL,
|
||||
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL,
|
||||
IN UINT32 CapsuleFwVersion,
|
||||
OUT CHAR16 **AbortReason,
|
||||
OUT UINT32 *LastAttemptStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UPDATE_CONFIG_DATA *ConfigData;
|
||||
UINTN TotalSize;
|
||||
UINTN BytesWritten;
|
||||
|
||||
if (Progress == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Invalid progress callback\n"));
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
|
||||
DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %d Images ...\n", ARRAY_SIZE (mUpdateConfigData)));
|
||||
|
||||
//
|
||||
// Compute total size of update
|
||||
//
|
||||
for (Index = 0, TotalSize = 0; Index < ARRAY_SIZE (mUpdateConfigData); Index++) {
|
||||
TotalSize += mUpdateConfigData[Index].Length;
|
||||
}
|
||||
|
||||
BytesWritten = 0;
|
||||
for (Index = 0, ConfigData = mUpdateConfigData; Index < ARRAY_SIZE (mUpdateConfigData); Index++, ConfigData++) {
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"PlatformUpdate(%d): BaseAddress - 0x%lx ImageOffset - 0x%x Length - 0x%x\n",
|
||||
Index,
|
||||
ConfigData->BaseAddress,
|
||||
ConfigData->ImageOffset,
|
||||
ConfigData->Length
|
||||
));
|
||||
Status = PerformFlashWriteWithProgress (
|
||||
ConfigData->FirmwareType, // FirmwareType
|
||||
ConfigData->BaseAddress, // FlashAddress
|
||||
ConfigData->AddressType, // FlashAddressType
|
||||
(VOID *)((UINTN)Image + (UINTN)ConfigData->ImageOffset), // Buffer
|
||||
ConfigData->Length, // BufferLength
|
||||
Progress, // Progress
|
||||
BytesWritten / TotalSize, // StartPercentage
|
||||
(BytesWritten + ConfigData->Length) * 80 / TotalSize // EndPercentage
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
BytesWritten += ConfigData->Length;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %r\n", Status));
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
*LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Lock the firmware device that contains a firmware image. Once a firmware
|
||||
device is locked, any attempts to modify the firmware image contents in the
|
||||
firmware device must fail.
|
||||
|
||||
@note It is recommended that all firmware devices support a lock method to
|
||||
prevent modifications to a stored firmware image.
|
||||
|
||||
@note A firmware device lock mechanism is typically only cleared by a full
|
||||
system reset (not just sleep state/low power mode).
|
||||
|
||||
@retval EFI_SUCCESS The firmware device was locked.
|
||||
@retval EFI_UNSUPPORTED The firmware device does not support locking
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FmpDeviceLock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
## @file
|
||||
# Provides firmware device specific services to support updates of a firmware
|
||||
# image stored in a firmware device.
|
||||
#
|
||||
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.30
|
||||
BASE_NAME = FmpDeviceLib
|
||||
FILE_GUID = BCBACAC2-1D1D-4C14-89A3-5E27496B702D
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = FmpDeviceLib|DXE_DRIVER UEFI_DRIVER
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
FmpDeviceLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
FmpDevicePkg/FmpDevicePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
MemoryAllocationLib
|
||||
PlatformFlashAccessLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision
|
||||
gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVersion
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
/** @file
|
||||
Platform Flash Access library.
|
||||
|
||||
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/VirtNorFlashDeviceLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include "PlatformFlashAccessLib.h"
|
||||
|
||||
#define ALIGN(v, a) (UINTN)((((v) - 1) | ((a) - 1)) + 1)
|
||||
|
||||
#define FLASH_CODE_BASE 0x20000000
|
||||
#define FLASH_DATA_BASE 0x22000000
|
||||
#define FLASH_SIZE SIZE_32MB
|
||||
#define BLOCK_SIZE SIZE_256KB
|
||||
|
||||
/**
|
||||
Perform flash write operation with progress indicator. The start and end
|
||||
completion percentage values are passed into this function. If the requested
|
||||
flash write operation is broken up, then completion percentage between the
|
||||
start and end values may be passed to the provided Progress function. The
|
||||
caller of this function is required to call the Progress function for the
|
||||
start and end completion percentage values. This allows the Progress,
|
||||
StartPercentage, and EndPercentage parameters to be ignored if the requested
|
||||
flash write operation can not be broken up
|
||||
|
||||
@param[in] FirmwareType The type of firmware.
|
||||
@param[in] FlashAddress The address of flash device to be accessed.
|
||||
@param[in] FlashAddressType The type of flash device address.
|
||||
@param[in] Buffer The pointer to the data buffer.
|
||||
@param[in] Length The length of data buffer in bytes.
|
||||
@param[in] Progress A function used report the progress of the
|
||||
firmware update. This is an optional parameter
|
||||
that may be NULL.
|
||||
@param[in] StartPercentage The start completion percentage value that may
|
||||
be used to report progress during the flash
|
||||
write operation.
|
||||
@param[in] EndPercentage The end completion percentage value that may
|
||||
be used to report progress during the flash
|
||||
write operation.
|
||||
|
||||
@retval EFI_SUCCESS The operation returns successfully.
|
||||
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
||||
@retval EFI_UNSUPPORTED The flash device access is unsupported.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PerformFlashWriteWithProgress (
|
||||
IN PLATFORM_FIRMWARE_TYPE FirmwareType,
|
||||
IN EFI_PHYSICAL_ADDRESS FlashAddress,
|
||||
IN FLASH_ADDRESS_TYPE FlashAddressType,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN Length,
|
||||
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
|
||||
IN UINTN StartPercentage,
|
||||
IN UINTN EndPercentage
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
UINTN LbaNum;
|
||||
UINTN Lba;
|
||||
UINTN Index;
|
||||
VOID *ShadowBuffer;
|
||||
UINTN LastBlock;
|
||||
UINTN NumByte;
|
||||
UINTN FlashBase;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
|
||||
|
||||
if (FlashAddressType != FlashAddressTypeAbsoluteAddress) {
|
||||
// Only support absolute address for this platform
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (FirmwareType == PlatformFirmwareTypeSystemFirmware) {
|
||||
if ((FlashAddress < FLASH_CODE_BASE) || ((FlashAddress + Length) > (FLASH_CODE_BASE + FLASH_SIZE))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FlashBase = FLASH_CODE_BASE;
|
||||
} else {
|
||||
if ((FlashAddress < FLASH_DATA_BASE) || ((FlashAddress + Length) > (FLASH_DATA_BASE + FLASH_SIZE))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FlashBase = FLASH_DATA_BASE;
|
||||
}
|
||||
|
||||
ShadowBuffer = AllocateZeroPool (BLOCK_SIZE);
|
||||
LastBlock = FLASH_SIZE / BLOCK_SIZE - 1;
|
||||
if ( (ALIGN (FlashAddress, BLOCK_SIZE) != FlashAddress)
|
||||
|| (Length % BLOCK_SIZE))
|
||||
{
|
||||
// Not expect un-aligned flash address
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Erase & Write
|
||||
//
|
||||
LbaNum = Length / BLOCK_SIZE;
|
||||
Lba = (FlashAddress - FlashBase) / BLOCK_SIZE;
|
||||
for (Index = 0; Index < LbaNum; Index++) {
|
||||
if (Progress != NULL) {
|
||||
Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / LbaNum));
|
||||
}
|
||||
|
||||
if (CompareMem (
|
||||
(UINT8 *)(UINTN)(GET_NOR_BLOCK_ADDRESS (FlashBase, Lba + Index, BLOCK_SIZE)),
|
||||
(UINT8 *)Buffer + Index * BLOCK_SIZE,
|
||||
BLOCK_SIZE
|
||||
) == 0)
|
||||
{
|
||||
DEBUG ((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));
|
||||
NumByte = BLOCK_SIZE;
|
||||
Status = NorFlashWriteSingleBlock (
|
||||
FlashBase,
|
||||
FlashBase,
|
||||
Lba + Index,
|
||||
LastBlock,
|
||||
BLOCK_SIZE,
|
||||
FLASH_SIZE,
|
||||
0,
|
||||
&NumByte,
|
||||
(UINT8 *)Buffer + Index * BLOCK_SIZE,
|
||||
ShadowBuffer
|
||||
);
|
||||
if ((Status != EFI_SUCCESS) || (NumByte != BLOCK_SIZE)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"Sector - 0x%x - update failed (bytes written)...\n",
|
||||
Index,
|
||||
NumByte
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Progress != NULL) {
|
||||
Progress (EndPercentage);
|
||||
}
|
||||
|
||||
FreePool (ShadowBuffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Perform flash write operation.
|
||||
|
||||
@param[in] FirmwareType The type of firmware.
|
||||
@param[in] FlashAddress The address of flash device to be accessed.
|
||||
@param[in] FlashAddressType The type of flash device address.
|
||||
@param[in] Buffer The pointer to the data buffer.
|
||||
@param[in] Length The length of data buffer in bytes.
|
||||
|
||||
@retval EFI_SUCCESS The operation returns successfully.
|
||||
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
||||
@retval EFI_UNSUPPORTED The flash device access is unsupported.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PerformFlashWrite (
|
||||
IN PLATFORM_FIRMWARE_TYPE FirmwareType,
|
||||
IN EFI_PHYSICAL_ADDRESS FlashAddress,
|
||||
IN FLASH_ADDRESS_TYPE FlashAddressType,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
return PerformFlashWriteWithProgress (
|
||||
FirmwareType,
|
||||
FlashAddress,
|
||||
FlashAddressType,
|
||||
Buffer,
|
||||
Length,
|
||||
NULL,
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Platform Flash Access Lib Constructor.
|
||||
|
||||
@retval EFI_SUCCESS Constructor returns successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PlatformFlashAccessLibConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// map the code flash region, the data flash region
|
||||
// already mapped via variable driver
|
||||
//
|
||||
Status = gDS->AddMemorySpace (
|
||||
EfiGcdMemoryTypeMemoryMappedIo,
|
||||
FLASH_CODE_BASE,
|
||||
SIZE_32MB,
|
||||
EFI_MEMORY_UC
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = gDS->SetMemorySpaceAttributes (
|
||||
FLASH_CODE_BASE,
|
||||
SIZE_32MB,
|
||||
EFI_MEMORY_UC
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/** @file
|
||||
Platform flash device access library.
|
||||
|
||||
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __PLATFORM_FLASH_ACCESS_LIB_H__
|
||||
#define __PLATFORM_FLASH_ACCESS_LIB_H__
|
||||
|
||||
#include <Protocol/FirmwareManagement.h>
|
||||
|
||||
typedef enum {
|
||||
FlashAddressTypeRelativeAddress,
|
||||
FlashAddressTypeAbsoluteAddress,
|
||||
} FLASH_ADDRESS_TYPE;
|
||||
|
||||
//
|
||||
// Type 0 ~ 0x7FFFFFFF is defined in this library.
|
||||
// Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM.
|
||||
//
|
||||
typedef enum {
|
||||
PlatformFirmwareTypeSystemFirmware,
|
||||
PlatformFirmwareTypeNvRam,
|
||||
} PLATFORM_FIRMWARE_TYPE;
|
||||
|
||||
/**
|
||||
Perform flash write operation.
|
||||
|
||||
@param[in] FirmwareType The type of firmware.
|
||||
@param[in] FlashAddress The address of flash device to be accessed.
|
||||
@param[in] FlashAddressType The type of flash device address.
|
||||
@param[in] Buffer The pointer to the data buffer.
|
||||
@param[in] Length The length of data buffer in bytes.
|
||||
|
||||
@retval EFI_SUCCESS The operation returns successfully.
|
||||
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
||||
@retval EFI_UNSUPPORTED The flash device access is unsupported.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PerformFlashWrite (
|
||||
IN PLATFORM_FIRMWARE_TYPE FirmwareType,
|
||||
IN EFI_PHYSICAL_ADDRESS FlashAddress,
|
||||
IN FLASH_ADDRESS_TYPE FlashAddressType,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN Length
|
||||
);
|
||||
|
||||
/**
|
||||
Perform flash write operation with progress indicator. The start and end
|
||||
completion percentage values are passed into this function. If the requested
|
||||
flash write operation is broken up, then completion percentage between the
|
||||
start and end values may be passed to the provided Progress function. The
|
||||
caller of this function is required to call the Progress function for the
|
||||
start and end completion percentage values. This allows the Progress,
|
||||
StartPercentage, and EndPercentage parameters to be ignored if the requested
|
||||
flash write operation can not be broken up
|
||||
|
||||
@param[in] FirmwareType The type of firmware.
|
||||
@param[in] FlashAddress The address of flash device to be accessed.
|
||||
@param[in] FlashAddressType The type of flash device address.
|
||||
@param[in] Buffer The pointer to the data buffer.
|
||||
@param[in] Length The length of data buffer in bytes.
|
||||
@param[in] Progress A function used report the progress of the
|
||||
firmware update. This is an optional parameter
|
||||
that may be NULL.
|
||||
@param[in] StartPercentage The start completion percentage value that may
|
||||
be used to report progress during the flash
|
||||
write operation.
|
||||
@param[in] EndPercentage The end completion percentage value that may
|
||||
be used to report progress during the flash
|
||||
write operation.
|
||||
|
||||
@retval EFI_SUCCESS The operation returns successfully.
|
||||
@retval EFI_WRITE_PROTECTED The flash device is read only.
|
||||
@retval EFI_UNSUPPORTED The flash device access is unsupported.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PerformFlashWriteWithProgress (
|
||||
IN PLATFORM_FIRMWARE_TYPE FirmwareType,
|
||||
IN EFI_PHYSICAL_ADDRESS FlashAddress,
|
||||
IN FLASH_ADDRESS_TYPE FlashAddressType,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN Length,
|
||||
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL,
|
||||
IN UINTN StartPercentage,
|
||||
IN UINTN EndPercentage
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
## @file
|
||||
# Platform Flash Access library.
|
||||
#
|
||||
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.30
|
||||
BASE_NAME = PlatformFlashAccessLibDxe
|
||||
FILE_GUID = 2FDAFAFE-0179-4047-90A4-40BC56CFBBAE
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = PlatformFlashAccessLib
|
||||
CONSTRUCTOR = PlatformFlashAccessLibConstructor
|
||||
|
||||
[Sources]
|
||||
PlatformFlashAccessLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
OvmfPkg/OvmfPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
PcdLib
|
||||
DebugLib
|
||||
VirtNorFlashDeviceLib
|
||||
UefiBootServicesTableLib
|
||||
DxeServicesTableLib
|
||||
|
|
@ -56,10 +56,20 @@
|
|||
!error "NETWORK_SNP_ENABLE is IA32/X64/EBC only"
|
||||
!endif
|
||||
|
||||
#
|
||||
# UPDATE/RECOVERY definition
|
||||
#
|
||||
DEFINE CAPSULE_ENABLE = FALSE
|
||||
DEFINE FMP_SYSTEM_DEVICE = BCBACAC2-1D1D-4C14-89A3-5E27496B702D
|
||||
|
||||
!include MdePkg/MdeLibs.dsc.inc
|
||||
!include NetworkPkg/Network.dsc.inc
|
||||
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
POSTBUILD = python OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py
|
||||
!include OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc
|
||||
!endif
|
||||
|
||||
[BuildOptions]
|
||||
GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
|
||||
!ifdef $(SOURCE_DEBUG_ENABLE)
|
||||
|
|
@ -119,6 +129,18 @@
|
|||
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf
|
||||
!endif
|
||||
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
|
||||
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
|
||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
|
||||
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
|
||||
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
|
||||
FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf
|
||||
DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibText/DisplayUpdateProgressLibText.inf
|
||||
RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
|
||||
!endif
|
||||
|
||||
[LibraryClasses.common.DXE_DRIVER]
|
||||
AcpiPlatformLib|OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf
|
||||
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
|
||||
|
|
@ -132,6 +154,11 @@
|
|||
UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
|
||||
PciExpressLib|OvmfPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
|
||||
!endif
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
|
||||
|
|
@ -231,6 +258,10 @@
|
|||
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0
|
||||
!endif
|
||||
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid|{GUID("$(FMP_SYSTEM_DEVICE)")}|VOID*|0x10
|
||||
!endif
|
||||
|
||||
[PcdsDynamicHii]
|
||||
gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGuid|0x0|FALSE|NV,BS
|
||||
|
||||
|
|
@ -491,3 +522,11 @@
|
|||
<LibraryClasses>
|
||||
NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf
|
||||
}
|
||||
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
|
||||
MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf {
|
||||
<LibraryClasses>
|
||||
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
|
||||
}
|
||||
!endif
|
||||
|
|
|
|||
|
|
@ -216,6 +216,11 @@ INF MdeModulePkg/Logo/LogoDxe.inf
|
|||
#
|
||||
INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
|
||||
|
||||
!if $(CAPSULE_ENABLE) == TRUE
|
||||
INF MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf
|
||||
INF FILE_GUID = $(FMP_SYSTEM_DEVICE) FmpDevicePkg/FmpDxe/FmpDxe.inf
|
||||
!endif
|
||||
|
||||
################################################################################
|
||||
|
||||
[FV.FVMAIN_COMPACT]
|
||||
|
|
|
|||
61
OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc
Normal file
61
OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
## @file
|
||||
# FmpDxe driver for system firmware update.
|
||||
#
|
||||
# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
FmpDevicePkg/FmpDxe/FmpDxe.inf {
|
||||
<Defines>
|
||||
#
|
||||
# ESRT and FMP GUID for system device capsule update
|
||||
#
|
||||
FILE_GUID = $(FMP_SYSTEM_DEVICE)
|
||||
|
||||
<PcdsFixedAtBuild>
|
||||
#
|
||||
# Unicode name string that is used to populate FMP Image Descriptor for this capsule update module
|
||||
#
|
||||
gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceImageIdName|L"RISC-V VIRT System Firmware Device"
|
||||
|
||||
#
|
||||
# ESRT and FMP Lowest Support Version for this capsule update module
|
||||
# 000.000.000.000
|
||||
#
|
||||
gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVersion|0x00000001
|
||||
|
||||
gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressWatchdogTimeInSeconds|2
|
||||
|
||||
#
|
||||
# Capsule Update Progress Bar Color. Set to Green (RGB) (0, 255, 0)
|
||||
#
|
||||
gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressColor|0x0000FF00
|
||||
|
||||
#
|
||||
# Certificates used to authenticate capsule update image
|
||||
# EDKII Test certificate
|
||||
#
|
||||
!include BaseTools/Source/Python/Pkcs7Sign/TestRoot.cer.gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr.inc
|
||||
|
||||
<LibraryClasses>
|
||||
#
|
||||
# Generic libraries that are used "as is" by all FMP modules
|
||||
#
|
||||
FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf
|
||||
FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf
|
||||
FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
|
||||
FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
|
||||
FmpDependencyDeviceLib|FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
|
||||
#
|
||||
# Platform specific capsule policy library
|
||||
#
|
||||
CapsuleUpdatePolicyLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf
|
||||
#
|
||||
# Device specific library that processes a capsule and updates the FW storage device
|
||||
#
|
||||
FmpDeviceLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf
|
||||
VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
|
||||
PlatformFlashAccessLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue