From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id 0FBD5941A73 for ; Mon, 21 Apr 2025 16:58:45 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=xp50VUixw+KCtQNw9BLE5qtciwqB8tcFpf/O+wIzImE=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240830; t=1745254725; v=1; x=1745513924; b=rwIs2I+lwvmjwx6AfGMI3cW/DQynOWrpd0nFMxZ1GR+fcdPRGzx5Y29Ij4gWVnukK928Sg2H D51+ZvwuU1IQdJ0MryKl3JPfZXQy8RNKFvENVMkOM+WlbmXEjwrvHFd3AsuE+w4YOf6bH8r5ZLG 5olJOzheRB1davUate7L11x3pg2iaLK5kxE+x51xJiR/fZD2/30Ae2rOUWgj5Y6M6edtJAUp2A3 u/h4MqMAirMGHM89t3pSzg+/3+BxP20RwrKM/jSdGmK1BrclsaNSGtbFA5ovbfx8EEtiEzzJ4Tr 1qrvTjBBqJ2Uvg+q74Ch7GwxR0ikzg3lgP+N1yqUkwPVA== X-Received: by 127.0.0.2 with SMTP id SwMkYY7687511xwDxtYDldIn; Mon, 21 Apr 2025 09:58:44 -0700 X-Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) by mx.groups.io with SMTP id smtpd.web10.19895.1745254723882790404 for ; Mon, 21 Apr 2025 09:58:43 -0700 X-Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-7390d21bb1cso3738502b3a.2 for ; Mon, 21 Apr 2025 09:58:43 -0700 (PDT) X-Gm-Message-State: TVVFV1u5KiGdKFcKP6sd03Frx7686176AA= X-Gm-Gg: ASbGnct+UCo1xTfwRGkj8+/3eeJm9NUCtxinBWvUJ0V5w5ir9VzzT+/nNN1cZMJhDx6 pPat8dshFJPPQ/IBDgyWlQ6i184uA/t+2Vz6ZuEWf4uSWEpAStWcZC8DP193gSkTZhrPCNFGdkD cdKAhEiQirkVyLKCbmROTEQBAWcIh4m0WcIr9dc7WPUWwcArnsF1HC5Jy4FWmKMT7/H5uvMa8zo eq9uaKevPeavx0vR3pCX1SkJo0BX7gT7Apw+m/Y1l7CNofte0ofHHjH4W1L9eDS48dwf9057GQU U+xwtBX67z44hYWFbAxKCwAwJAkqVqOQZ8ziBXyFRu8fNZZSgdNnOnHokMkgIYhtDbFGIa5ayUs LSHMvhO5ULcsZ6rVT8Bgl8kGjeFjYMsRRts7z+cR6tw== X-Google-Smtp-Source: AGHT+IEQOvXk8LnbuRCZhfvxmLxqPH/0KRyqA8ZVGxc8IpgKOVQ1Stt/+EHMoDNitXSHys+je43zqQ== X-Received: by 2002:a05:6a00:1d81:b0:736:39d4:ccf6 with SMTP id d2e1a72fcca58-73dc14a934cmr16860337b3a.8.1745254722048; Mon, 21 Apr 2025 09:58:42 -0700 (PDT) X-Received: from DESKTOP-I1ETA6N.dc1.ventanamicro.com (c-174-50-177-196.hsd1.ca.comcast.net. [174.50.177.196]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-73dbfa59f87sm7055330b3a.91.2025.04.21.09.58.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 09:58:41 -0700 (PDT) From: "Tuan Phan" To: devel@edk2.groups.io Cc: andyw@imsa.edu, maobibo@loongson.cn, lichao@loongson.cn, kraxel@redhat.com, jiewen.yao@intel.com, leif.lindholm@oss.qualcomm.com, sami.mujawar@arm.com, sunilvl@ventanamicro.com, ardb+tianocore@kernel.org, lixianglai@loongson.cn, Tuan Phan Subject: [edk2-devel] [PATCH 3/3] OvmfPkg/RiscVVirt: Add support for Capsule Firmware Upgrade Date: Mon, 21 Apr 2025 09:58:19 -0700 Message-Id: <20250421165819.18451-4-tphan@ventanamicro.com> In-Reply-To: <20250421165819.18451-1-tphan@ventanamicro.com> References: <20250421165819.18451-1-tphan@ventanamicro.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Mon, 21 Apr 2025 09:58:44 -0700 Resent-From: tphan@ventanamicro.com Reply-To: devel@edk2.groups.io,tphan@ventanamicro.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240830 header.b=rwIs2I+l; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io This patch introduces support for firmware upgrades using the FMP capsule update mechanism. Signed-off-by: Tuan Phan --- OvmfPkg/OvmfPkg.ci.yaml | 3 +- .../Capsule/GenerateCapsule/GenCapsule.py | 332 ++++++++ .../CapsuleUpdatePolicyLib.c | 121 +++ .../CapsuleUpdatePolicyLib.inf | 29 + .../CapsuleUpdatePolicyLib.uni | 12 + .../Library/FmpDeviceLib/FmpDeviceLib.c | 774 ++++++++++++++++++ .../Library/FmpDeviceLib/FmpDeviceLib.inf | 46 ++ .../PlatformFlashAccessLib.c | 236 ++++++ .../PlatformFlashAccessLib.h | 95 +++ .../PlatformFlashAccessLib.inf | 34 + OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc | 39 + OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf | 5 + OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc | 61 ++ 13 files changed, 1786 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCa= psule.py create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdate= PolicyLib/CapsuleUpdatePolicyLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdate= PolicyLib/CapsuleUpdatePolicyLib.inf create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdate= PolicyLib/CapsuleUpdatePolicyLib.uni create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/= FmpDeviceLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/= FmpDeviceLib.inf create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlash= AccessLib/PlatformFlashAccessLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlash= AccessLib/PlatformFlashAccessLib.h create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlash= AccessLib/PlatformFlashAccessLib.inf create mode 100644 OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc diff --git a/OvmfPkg/OvmfPkg.ci.yaml b/OvmfPkg/OvmfPkg.ci.yaml index e4b729b4a80e..056e681b3dd2 100644 --- a/OvmfPkg/OvmfPkg.ci.yaml +++ b/OvmfPkg/OvmfPkg.ci.yaml @@ -53,7 +53,8 @@ "UefiCpuPkg/UefiCpuPkg.dec",=0D "ShellPkg/ShellPkg.dec",=0D "EmbeddedPkg/EmbeddedPkg.dec",=0D - "SourceLevelDebugPkg/SourceLevelDebugPkg.dec"=0D + "SourceLevelDebugPkg/SourceLevelDebugPkg.dec",=0D + "FmpDevicePkg/FmpDevicePkg.dec"=0D ],=0D # For host based unit tests=0D "AcceptableDependencies-HOST_APPLICATION":[=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.p= y b/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py new file mode 100644 index 000000000000..1889328fb9ba --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py @@ -0,0 +1,332 @@ +## @file=0D +# Generate capsules for RiscVVirt platform=0D +# openssl, gcab must be install and in path=0D +#=0D +# Copyright (c) 2019, Intel Corporation. All rights reserved.
=0D +# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +=0D +'''=0D +GenCapsuleAll=0D +'''=0D +=0D +import os=0D +import sys=0D +import argparse=0D +import subprocess=0D +import glob=0D +import shutil=0D +import struct=0D +import datetime=0D +=0D +#=0D +# Globals for help information=0D +#=0D +__prog__ =3D 'GenCapsuleAll'=0D +__copyright__ =3D 'Copyright (c) 2019, Intel Corporation. All rights res= erved.'=0D +__description__ =3D 'Generate RiscVVirt capsules.\n'=0D +=0D +#=0D +# Globals=0D +#=0D +gWorkspace =3D ''=0D +gBaseToolsPath =3D ''=0D +gArgs =3D None=0D +=0D +def LogAlways(Message):=0D + sys.stdout.write (__prog__ + ': ' + Message + '\n')=0D + sys.stdout.flush()=0D +=0D +def Log(Message):=0D + global gArgs=0D + if not gArgs.Verbose:=0D + return=0D + sys.stdout.write (__prog__ + ': ' + Message + '\n')=0D + sys.stdout.flush()=0D +=0D +def Error(Message, ExitValue=3D1):=0D + sys.stderr.write (__prog__ + ': ERROR: ' + Message + '\n')=0D + sys.exit (ExitValue)=0D +=0D +def RelativePath(target):=0D + global gWorkspace=0D + Log('RelativePath' + target)=0D + return os.path.relpath (target, gWorkspace)=0D +=0D +def NormalizePath(target):=0D + if isinstance(target, tuple):=0D + return os.path.normpath (os.path.join (*target))=0D + else:=0D + return os.path.normpath (target)=0D +=0D +def RemoveFile(target):=0D + target =3D NormalizePath(target)=0D + if not target or target =3D=3D os.pathsep:=0D + Error ('RemoveFile() invalid target')=0D + if os.path.exists(target):=0D + os.remove (target)=0D + Log ('remove %s' % (RelativePath (target)))=0D +=0D +def RemoveDirectory(target):=0D + target =3D NormalizePath(target)=0D + if not target or target =3D=3D os.pathsep:=0D + Error ('RemoveDirectory() invalid target')=0D + if os.path.exists(target):=0D + Log ('rmdir %s' % (RelativePath (target)))=0D + shutil.rmtree(target)=0D +=0D +def CreateDirectory(target):=0D + target =3D NormalizePath(target)=0D + if not os.path.exists(target):=0D + Log ('mkdir %s' % (RelativePath (target)))=0D + os.makedirs (target)=0D +=0D +def Copy(src, dst):=0D + src =3D NormalizePath(src)=0D + dst =3D NormalizePath(dst)=0D + for File in glob.glob(src):=0D + Log ('copy %s -> %s' % (RelativePath (File), RelativePath (dst)))= =0D + shutil.copy (File, dst)=0D +=0D +GenerateCapsuleCommand =3D '''=0D +GenerateCapsule=0D +--encode=0D +--guid {FMP_CAPSULE_GUID}=0D +--fw-version {FMP_CAPSULE_VERSION}=0D +--lsv {FMP_CAPSULE_LSV}=0D +--signer-private-cert=3D{BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestCert= .pem=0D +--other-public-cert=3D{BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestSub.pu= b.pem=0D +--trusted-public-cert=3D{BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestRoot= .pub.pem=0D +-o {FMP_CAPSULE_FILE}=0D +{FMP_CAPSULE_PAYLOAD}=0D +'''=0D +MetaInfoXmlTemplate =3D '''=0D +=0D +=0D + com.intel.FMP_CAPSULE_BASE_NAME.firmware=0D + FMP_CAPSULE_BASE_NAME=0D + System firmware for the FMP_CAPSULE_BASE_NAME=0D + =0D + Description of System firmware for the FMP_CAPSULE_BASE_NAME=0D + =0D + =0D + FMP_CAPSULE_GUID=0D + =0D + http://www.tianocore.org=0D + CC0-1.0=0D + BSD=0D + Tianocore=0D + =0D + =0D + =0D + Build FMP_CAPSULE_STRING=0D + =0D + =0D + =0D + =0D + =0D + =0D + =0D +=0D +'''=0D +=0D +def GenCapsuleDevice (BaseName, PayloadFileName, Guid, Version, Lsv, Capsu= lesPath, CapsulesSubDir):=0D + global gBaseToolsPath=0D + LogAlways ('Generate Capsule: {0} {1:08x} {2:08x} {3}'.format (Guid, V= ersion, Lsv, PayloadFileName))=0D +=0D + VersionString =3D '.'.join([str(ord(x)) for x in struct.pack('>I', Ver= sion).decode()])=0D +=0D + FmpCapsuleFile =3D NormalizePath ((CapsulesPath, CapsulesSubDir, BaseN= ame + '.' + VersionString + '.cap'))=0D + Command =3D GenerateCapsuleCommand.format (=0D + FMP_CAPSULE_GUID =3D Guid,=0D + FMP_CAPSULE_VERSION =3D Version,=0D + FMP_CAPSULE_LSV =3D Lsv,=0D + BASE_TOOLS_PATH =3D gBaseToolsPath,=0D + FMP_CAPSULE_FILE =3D FmpCapsuleFile,=0D + FMP_CAPSULE_PAYLOAD =3D PayloadFileName=0D + )=0D + Command =3D ' '.join(Command.splitlines()).strip()=0D + if gArgs.Verbose:=0D + Command =3D Command + ' -v'=0D +=0D + Log (Command)=0D +=0D + Process =3D subprocess.Popen(Command, stdin=3Dsubprocess.PIPE, stdout= =3Dsubprocess.PIPE, stderr=3Dsubprocess.PIPE, shell=3DTrue)=0D + ProcessOutput =3D Process.communicate()=0D +=0D + if Process.returncode =3D=3D 0:=0D + Log (ProcessOutput[0].decode())=0D + else:=0D + LogAlways (Command)=0D + LogAlways (ProcessOutput[0].decode())=0D + Error ('GenerateCapsule returned an error')=0D +=0D + Copy (PayloadFileName, (CapsulesPath, 'firmware.bin'))=0D + MetaInfoXml =3D MetaInfoXmlTemplate=0D + MetaInfoXml =3D MetaInfoXml.replace ('FMP_CAPSULE_GUID', Guid)=0D + MetaInfoXml =3D MetaInfoXml.replace ('FMP_CAPSULE_BASE_NAME', BaseName= )=0D + MetaInfoXml =3D MetaInfoXml.replace ('FMP_CAPSULE_VERSION_DECIMAL', st= r(Version))=0D + MetaInfoXml =3D MetaInfoXml.replace ('FMP_CAPSULE_STRING', VersionStri= ng)=0D + MetaInfoXml =3D MetaInfoXml.replace ('FMP_CAPSULE_DATE', str(datetime.= date.today()))=0D + f =3D open (NormalizePath ((CapsulesPath, 'firmware.metainfo.xml')), '= w')=0D + f.write(MetaInfoXml)=0D + f.close()=0D +=0D + Command =3D 'gcab --create firmware.cab firmware.bin firmware.metainfo= .xml'=0D + Log (Command)=0D +=0D + Process =3D subprocess.Popen(Command, cwd=3DCapsulesPath, stdin=3Dsubp= rocess.PIPE, stdout=3Dsubprocess.PIPE, stderr=3Dsubprocess.PIPE, shell=3DTr= ue)=0D + ProcessOutput =3D Process.communicate()=0D +=0D + if Process.returncode =3D=3D 0:=0D + Log (ProcessOutput[0].decode())=0D + else:=0D + LogAlways (Command)=0D + LogAlways (ProcessOutput[0].decode())=0D + Error ('GenerateCapsule returned an error')=0D +=0D + FmpCabinetFile =3D NormalizePath ((CapsulesPath, CapsulesSubDir, BaseN= ame + '.' + VersionString + '.cab'))=0D +=0D + Copy ((CapsulesPath, 'firmware.cab'), FmpCabinetFile)=0D +=0D + RemoveFile ((CapsulesPath, 'firmware.cab'))=0D + RemoveFile ((CapsulesPath, 'firmware.metainfo.xml'))=0D + RemoveFile ((CapsulesPath, 'firmware.bin'))=0D +=0D +if __name__ =3D=3D '__main__':=0D + #=0D + # Create command line argument parser object=0D + #=0D + parser =3D argparse.ArgumentParser (=0D + prog =3D __prog__,=0D + description =3D __description__ + __copyright__,=0D + conflict_handler =3D 'resolve'=0D + )=0D + parser.add_argument (=0D + '-a', '--arch', dest =3D 'Arch', nargs =3D '+', action =3D 'a= ppend',=0D + required =3D True,=0D + help =3D '''ARCHS is one of list: IA32, X64, IPF, ARM, AARCH6= 4, RISCV64=0D + or EBC, which overrides target.txt's TARGET_ARCH de= finition.=0D + To specify more archs, please repeat this option.''= '=0D + )=0D + parser.add_argument (=0D + '-t', '--tagname', dest =3D 'ToolChain', required =3D True,=0D + help =3D '''Using the Tool Chain Tagname to build the platfor= m,=0D + overriding target.txt's TOOL_CHAIN_TAG definition.'= ''=0D + )=0D + parser.add_argument (=0D + '-p', '--platform', dest =3D 'PlatformFile', required =3D Tru= e,=0D + help =3D '''Build the platform specified by the DSC file name= argument,=0D + overriding target.txt's ACTIVE_PLATFORM definition.= '''=0D + )=0D + parser.add_argument (=0D + '-b', '--buildtarget', dest =3D 'BuildTarget', required =3D T= rue,=0D + help =3D '''Using the TARGET to build the platform, overridin= g=0D + target.txt's TARGET definition.'''=0D + )=0D + parser.add_argument (=0D + '--conf=3D', dest =3D 'ConfDirectory', required =3D True,=0D + help =3D '''Specify the customized Conf directory.'''=0D + )=0D + parser.add_argument (=0D + '-D', '--define', dest =3D 'Define', nargs=3D'*', action =3D = 'append',=0D + help =3D '''Macro: "Name [=3D Value]".'''=0D + )=0D + parser.add_argument (=0D + '-v', '--verbose', dest =3D 'Verbose', action =3D 'store_true= ',=0D + help =3D '''Turn on verbose output with informational message= s printed'''=0D + )=0D + parser.add_argument (=0D + '--package', dest =3D 'Package', nargs =3D '*', action =3D 'a= ppend',=0D + help =3D '''The directory name of a package of tests to copy'= ''=0D + )=0D +=0D + #=0D + # Parse command line arguments=0D + #=0D + gArgs, remaining =3D parser.parse_known_args()=0D + gArgs.BuildType =3D 'all'=0D + for BuildType in ['all', 'fds', 'genc', 'genmake', 'clean', 'cleanall'= , 'modules', 'libraries', 'run']:=0D + if BuildType in remaining:=0D + gArgs.BuildType =3D BuildType=0D + remaining.remove(BuildType)=0D + break=0D + gArgs.Remaining =3D ' '.join(remaining)=0D +=0D + #=0D + # Get WORKSPACE environment variable=0D + #=0D + try:=0D + gWorkspace =3D os.environ['WORKSPACE']=0D + except:=0D + Error ('WORKSPACE environment variable not set')=0D +=0D + #=0D + # Get PACKAGES_PATH and generate prioritized list of paths=0D + #=0D + PathList =3D [gWorkspace]=0D + try:=0D + PathList +=3D os.environ['PACKAGES_PATH'].split(os.pathsep)=0D + except:=0D + pass=0D +=0D + #=0D + # Determine full path to BaseTools=0D + #=0D + for Path in PathList:=0D + if os.path.exists (os.path.join (Path, 'BaseTools')):=0D + gBaseToolsPath =3D os.path.join (Path, 'BaseTools')=0D + break=0D +=0D + #=0D + # Parse PLATFORM_NAME from DSC file=0D + #=0D + for Path in PathList:=0D + if os.path.exists (os.path.join (Path, gArgs.PlatformFile)):=0D + Dsc =3D open (os.path.join (Path, gArgs.PlatformFile), 'r').re= adlines()=0D + break=0D + for Line in Dsc:=0D + if Line.strip().startswith('PLATFORM_NAME'):=0D + OutputDirectory =3D os.path.join ('Build', Line.strip().split(= '=3D')[1].strip())=0D + break=0D +=0D + #=0D + # Determine full paths to EDK II build directory, EDK II build output= =0D + # directory and the CPU arch of the UEFI phase.=0D + #=0D + CommandDir =3D os.path.dirname(sys.argv[0])=0D + EdkiiBuildDir =3D os.path.join (gWorkspace, OutputDirectory)=0D + EdkiiBuildOutput =3D os.path.join (EdkiiBuildDir, gArgs.BuildTarget + = '_' + gArgs.ToolChain)=0D + UefiArch =3D gArgs.Arch[0][0]=0D + if len (gArgs.Arch) > 1:=0D + if ['RISCV64'] in gArgs.Arch:=0D + UefiArch =3D 'RISCV64'=0D +=0D + CapsulesPath =3D NormalizePath((EdkiiBuildDir, 'Capsules'))=0D +=0D + CapsulesSubDir =3D 'TestCert' + '_' + UefiArch + '_' + gArgs.BuildTarg= et + '_' + gArgs.ToolChain=0D +=0D + #=0D + # Create output directories=0D + #=0D + try:=0D + CreateDirectory ((CapsulesPath))=0D + except:=0D + pass=0D + try:=0D + CreateDirectory ((CapsulesPath, CapsulesSubDir))=0D + except:=0D + pass=0D +=0D + #=0D + # Copy CapsuleApp=0D + #=0D + Copy ((EdkiiBuildOutput, UefiArch, 'CapsuleApp.efi'), (CapsulesPath, C= apsulesSubDir))=0D +=0D + #=0D + # Generate capsules for RiscVVirt Firmware Updates=0D + #=0D + CodeFW =3D os.path.join (EdkiiBuildOutput, 'FV', 'RISCV_VIRT_CODE.fd')= =0D + GenCapsuleDevice('RISCVVIRT', CodeFW,'bcbacac2-1d1d-4c14-89a3-5e27496b= 702d',0x00010000,0x00000000, CapsulesPath, CapsulesSubDir)=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyL= ib/CapsuleUpdatePolicyLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/Cap= suleUpdatePolicyLib/CapsuleUpdatePolicyLib.c new file mode 100644 index 000000000000..3d1adfac1849 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/Caps= uleUpdatePolicyLib.c @@ -0,0 +1,121 @@ +/** @file=0D + Provides platform policy services used during a capsule update.=0D +=0D + Copyright (c) 2016, Microsoft Corporation. All rights reserved.
=0D + Copyright (c) 2018, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +=0D +/**=0D + Determine if the system power state supports a capsule update.=0D +=0D + @param[out] Good Returns TRUE if system power state supports a capsule= =0D + update. Returns FALSE if system power state does not= =0D + support a capsule update. Return value is only valid = if=0D + return status is EFI_SUCCESS.=0D +=0D + @retval EFI_SUCCESS Good parameter has been updated with resu= lt.=0D + @retval EFI_INVALID_PARAMETER Good is NULL.=0D + @retval EFI_DEVICE_ERROR System power state can not be determined.= =0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +CheckSystemPower (=0D + OUT BOOLEAN *Good=0D + )=0D +{=0D + *Good =3D TRUE;=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Determines if the system thermal state supports a capsule update.=0D +=0D + @param[out] Good Returns TRUE if system thermal state supports a capsul= e=0D + update. Returns FALSE if system thermal state does no= t=0D + support a capsule update. Return value is only valid = if=0D + return status is EFI_SUCCESS.=0D +=0D + @retval EFI_SUCCESS Good parameter has been updated with resu= lt.=0D + @retval EFI_INVALID_PARAMETER Good is NULL.=0D + @retval EFI_DEVICE_ERROR System thermal state can not be determine= d.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +CheckSystemThermal (=0D + OUT BOOLEAN *Good=0D + )=0D +{=0D + *Good =3D TRUE;=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Determines if the system environment state supports a capsule update.=0D +=0D + @param[out] Good Returns TRUE if system environment state supports a ca= psule=0D + update. Returns FALSE if system environment state doe= s not=0D + support a capsule update. Return value is only valid = if=0D + return status is EFI_SUCCESS.=0D +=0D + @retval EFI_SUCCESS Good parameter has been updated with resu= lt.=0D + @retval EFI_INVALID_PARAMETER Good is NULL.=0D + @retval EFI_DEVICE_ERROR System environment state can not be deter= mined.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +CheckSystemEnvironment (=0D + OUT BOOLEAN *Good=0D + )=0D +{=0D + *Good =3D TRUE;=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Determines if the Lowest Supported Version checks should be performed. = The=0D + expected result from this function is TRUE. A platform can choose to re= turn=0D + FALSE (e.g. during manufacturing or servicing) to allow a capsule update= to a=0D + version below the current Lowest Supported Version.=0D +=0D + @retval TRUE The lowest supported version check is required.=0D + @retval FALSE Do not perform lowest support version check.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +IsLowestSupportedVersionCheckRequired (=0D + VOID=0D + )=0D +{=0D + return TRUE;=0D +}=0D +=0D +/**=0D + Determines if the FMP device should be locked when the event specified b= y=0D + PcdFmpDeviceLockEventGuid is signaled. The expected result from this fun= ction=0D + is TRUE so the FMP device is always locked. A platform can choose to re= turn=0D + FALSE (e.g. during manufacturing) to allow FMP devices to remain unlocke= d.=0D +=0D + @retval TRUE The FMP device lock action is required at lock event guid= .=0D + @retval FALSE Do not perform FMP device lock at lock event guid.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +IsLockFmpDeviceAtLockEventGuidRequired (=0D + VOID=0D + )=0D +{=0D + // Not lock FMP device for this platform=0D + return FALSE;=0D +}=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyL= ib/CapsuleUpdatePolicyLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/C= apsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf new file mode 100644 index 000000000000..fcefadd0551d --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/Caps= uleUpdatePolicyLib.inf @@ -0,0 +1,29 @@ +## @file=0D +# Provides platform policy services used during a capsule update.=0D +#=0D +# Copyright (c) 2016, Microsoft Corporation. All rights reserved.
=0D +# Copyright (c) 2018, Intel Corporation. All rights reserved.
=0D +# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 1.30=0D + BASE_NAME =3D CapsuleUpdatePolicyLib=0D + MODULE_UNI_FILE =3D CapsuleUpdatePolicyLib.uni=0D + FILE_GUID =3D 3ed188f7-7aba-47ff-bdeb-2ac23287a5ea=0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D CapsuleUpdatePolicyLib=0D +=0D +#=0D +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 RISCV64=0D +#=0D +=0D +[Sources]=0D + CapsuleUpdatePolicyLib.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + FmpDevicePkg/FmpDevicePkg.dec=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyL= ib/CapsuleUpdatePolicyLib.uni b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/C= apsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni new file mode 100644 index 000000000000..d26e716b11ad --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/Caps= uleUpdatePolicyLib.uni @@ -0,0 +1,12 @@ +// /** @file=0D +// Provides platform policy services used during a capsule update.=0D +//=0D +// Copyright (c) 2018, Intel Corporation. All rights reserved.
=0D +//=0D +// SPDX-License-Identifier: BSD-2-Clause-Patent=0D +//=0D +// **/=0D +=0D +#string STR_MODULE_ABSTRACT #language en-US "Provides platform policy= services used during a capsule update."=0D +=0D +#string STR_MODULE_DESCRIPTION #language en-US "Provides platform policy= services used during a capsule update."=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDevi= ceLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceL= ib.c new file mode 100644 index 000000000000..4fe21b763d5b --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c @@ -0,0 +1,774 @@ +/** @file=0D + Provides firmware device specific services to support updates of a firmw= are=0D + image stored in a firmware device.=0D +=0D + Copyright (c) Microsoft Corporation.
=0D + Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "../PlatformFlashAccessLib/PlatformFlashAccessLib.h"=0D +=0D +#define __BUILD_STRING(x) L ## #x=0D +#define BUILD_STRING(x) L"build #" __BUILD_STRING(x)=0D +#define CURRENT_FIRMWARE_VERSION FixedPcdGet32 (PcdFirmwareRevisio= n)=0D +#define CURRENT_FIRMWARE_VERSION_STRING BUILD_STRING (CURRENT_FIRMWARE_VE= RSION)=0D +=0D +typedef struct {=0D + PLATFORM_FIRMWARE_TYPE FirmwareType;=0D + FLASH_ADDRESS_TYPE AddressType;=0D + EFI_PHYSICAL_ADDRESS BaseAddress;=0D + UINTN Length;=0D + UINTN ImageOffset;=0D +} UPDATE_CONFIG_DATA;=0D +=0D +UPDATE_CONFIG_DATA mUpdateConfigData[] =3D {=0D + { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeAbsoluteAddress, 0= x20000000, 0x00800000, 0x00000000 },=0D +};=0D +=0D +/**=0D + Provide a function to install the Firmware Management Protocol instance = onto a=0D + device handle when the device is managed by a driver that follows the UE= FI=0D + Driver Model. If the device is not managed by a driver that follows the= UEFI=0D + Driver Model, then EFI_UNSUPPORTED is returned.=0D +=0D + @param[in] FmpInstaller Function that installs the Firmware Management= =0D + Protocol.=0D +=0D + @retval EFI_SUCCESS The device is managed by a driver that follows = the=0D + UEFI Driver Model. FmpInstaller must be called= on=0D + each Driver Binding Start().=0D + @retval EFI_UNSUPPORTED The device is not managed by a driver that foll= ows=0D + the UEFI Driver Model.=0D + @retval other The Firmware Management Protocol for this firmw= are=0D + device is not installed. The firmware device i= s=0D + still locked using FmpDeviceLock().=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +RegisterFmpInstaller (=0D + IN FMP_DEVICE_LIB_REGISTER_FMP_INSTALLER Function=0D + )=0D +{=0D + //=0D + // This is a system firmware update that does not use Driver Binding Pro= tocol=0D + //=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Provide a function to uninstall the Firmware Management Protocol instanc= e from a=0D + device handle when the device is managed by a driver that follows the UE= FI=0D + Driver Model. If the device is not managed by a driver that follows the= UEFI=0D + Driver Model, then EFI_UNSUPPORTED is returned.=0D +=0D + @param[in] FmpUninstaller Function that installs the Firmware Managemen= t=0D + Protocol.=0D +=0D + @retval EFI_SUCCESS The device is managed by a driver that follows = the=0D + UEFI Driver Model. FmpUninstaller must be call= ed on=0D + each Driver Binding Stop().=0D + @retval EFI_UNSUPPORTED The device is not managed by a driver that foll= ows=0D + the UEFI Driver Model.=0D + @retval other The Firmware Management Protocol for this firmw= are=0D + device is not installed. The firmware device i= s=0D + still locked using FmpDeviceLock().=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +RegisterFmpUninstaller (=0D + IN FMP_DEVICE_LIB_REGISTER_FMP_UNINSTALLER Function=0D + )=0D +{=0D + //=0D + // This is a system firmware update that does not use Driver Binding Pro= tocol=0D + //=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Set the device context for the FmpDeviceLib services when the device is= =0D + managed by a driver that follows the UEFI Driver Model. If the device i= s not=0D + managed by a driver that follows the UEFI Driver Model, then EFI_UNSUPPO= RTED=0D + is returned. Once a device context is set, the FmpDeviceLib services=0D + operate on the currently set device context.=0D +=0D + @param[in] Handle Device handle for the FmpDeviceLib services.=0D + If Handle is NULL, then Context is freed.=0D + @param[in, out] Context Device context for the FmpDeviceLib services.=0D + If Context is NULL, then a new context is alloc= ated=0D + for Handle and the current device context is se= t and=0D + returned in Context. If Context is not NULL, t= hen=0D + the current device context is set.=0D +=0D + @retval EFI_SUCCESS The device is managed by a driver that follows = the=0D + UEFI Driver Model.=0D + @retval EFI_UNSUPPORTED The device is not managed by a driver that foll= ows=0D + the UEFI Driver Model.=0D + @retval other The Firmware Management Protocol for this firmw= are=0D + device is not installed. The firmware device i= s=0D + still locked using FmpDeviceLock().=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceSetContext (=0D + IN EFI_HANDLE Handle,=0D + IN OUT VOID **Context=0D + )=0D +{=0D + //=0D + // This is a system firmware update that does not use Driver Binding Pro= tocol=0D + //=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Returns the size, in bytes, of the firmware image currently stored in th= e=0D + firmware device. This function is used to by the GetImage() and=0D + GetImageInfo() services of the Firmware Management Protocol. If the ima= ge=0D + size can not be determined from the firmware device, then 0 must be retu= rned.=0D +=0D + @param[out] Size Pointer to the size, in bytes, of the firmware image=0D + currently stored in the firmware device.=0D +=0D + @retval EFI_SUCCESS The size of the firmware image currently= =0D + stored in the firmware device was returne= d.=0D + @retval EFI_INVALID_PARAMETER Size is NULL.=0D + @retval EFI_UNSUPPORTED The firmware device does not support repo= rting=0D + the size of the currently stored firmware= image.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to determine= the=0D + size of the firmware image currently stor= ed in=0D + in the firmware device.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetSize (=0D + OUT UINTN *Size=0D + )=0D +{=0D + if (Size =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Returns the GUID value used to fill in the ImageTypeId field of the=0D + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImage= Info()=0D + service of the Firmware Management Protocol. If EFI_UNSUPPORTED is retu= rned,=0D + then the ImageTypeId field is set to gEfiCallerIdGuid. If EFI_SUCCESS i= s=0D + returned, then ImageTypeId is set to the Guid returned from this functio= n.=0D +=0D + @param[out] Guid Double pointer to a GUID value that is updated to poin= t to=0D + to a GUID value. The GUID value is not allocated and = must=0D + not be modified or freed by the caller.=0D +=0D + @retval EFI_SUCCESS EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID = is set=0D + to the returned Guid value.=0D + @retval EFI_UNSUPPORTED EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID = is set=0D + to gEfiCallerIdGuid.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetImageTypeIdGuidPtr (=0D + OUT EFI_GUID **Guid=0D + )=0D +{=0D + *Guid =3D &gEfiCallerIdGuid;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Returns values used to fill in the AttributesSupported and AttributesSet= tings=0D + fields of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned b= y the=0D + GetImageInfo() service of the Firmware Management Protocol. The followi= ng=0D + bit values from the Firmware Management Protocol may be combined:=0D + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE=0D + IMAGE_ATTRIBUTE_RESET_REQUIRED=0D + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED=0D + IMAGE_ATTRIBUTE_IN_USE=0D + IMAGE_ATTRIBUTE_UEFI_IMAGE=0D +=0D + @param[out] Supported Attributes supported by this firmware device.=0D + @param[out] Setting Attributes settings for this firmware device.=0D +=0D + @retval EFI_SUCCESS The attributes supported by the firmware= =0D + device were returned.=0D + @retval EFI_INVALID_PARAMETER Supported is NULL.=0D + @retval EFI_INVALID_PARAMETER Setting is NULL.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetAttributes (=0D + OUT UINT64 *Supported,=0D + OUT UINT64 *Setting=0D + )=0D +{=0D + if ((Supported =3D=3D NULL) || (Setting =3D=3D NULL)) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *Supported =3D (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |=0D + IMAGE_ATTRIBUTE_RESET_REQUIRED |=0D + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |=0D + IMAGE_ATTRIBUTE_IN_USE=0D + );=0D + *Setting =3D (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |=0D + IMAGE_ATTRIBUTE_RESET_REQUIRED |=0D + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |=0D + IMAGE_ATTRIBUTE_IN_USE=0D + );=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Returns the value used to fill in the LowestSupportedVersion field of th= e=0D + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImage= Info()=0D + service of the Firmware Management Protocol. If EFI_SUCCESS is returned= , then=0D + the firmware device supports a method to report the LowestSupportedVersi= on=0D + value from the currently stored firmware image. If the value can not be= =0D + reported for the firmware image currently stored in the firmware device,= then=0D + EFI_UNSUPPORTED must be returned. EFI_DEVICE_ERROR is returned if an er= ror=0D + occurs attempting to retrieve the LowestSupportedVersion value for the=0D + currently stored firmware image.=0D +=0D + @note It is recommended that all firmware devices support a method to re= port=0D + the LowestSupportedVersion value from the currently stored firmwar= e=0D + image.=0D +=0D + @param[out] LowestSupportedVersion LowestSupportedVersion value retriev= ed=0D + from the currently stored firmware i= mage.=0D +=0D + @retval EFI_SUCCESS The lowest supported version of currently stor= ed=0D + firmware image was returned in LowestSupported= Version.=0D + @retval EFI_UNSUPPORTED The firmware device does not support a method = to=0D + report the lowest supported version of the cur= rently=0D + stored firmware image.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the l= owest=0D + supported version of the currently stored firm= ware=0D + image.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetLowestSupportedVersion (=0D + OUT UINT32 *LowestSupportedVersion=0D + )=0D +{=0D + *LowestSupportedVersion =3D PcdGet32 (PcdFmpDeviceBuildTimeLowestSupport= edVersion);=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Returns the Null-terminated Unicode string that is used to fill in the=0D + VersionName field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is= =0D + returned by the GetImageInfo() service of the Firmware Management Protoc= ol.=0D + The returned string must be allocated using EFI_BOOT_SERVICES.AllocatePo= ol().=0D +=0D + @note It is recommended that all firmware devices support a method to re= port=0D + the VersionName string from the currently stored firmware image.=0D +=0D + @param[out] VersionString The version string retrieved from the current= ly=0D + stored firmware image.=0D +=0D + @retval EFI_SUCCESS The version string of currently stored=0D + firmware image was returned in Version.=0D + @retval EFI_INVALID_PARAMETER VersionString is NULL.=0D + @retval EFI_UNSUPPORTED The firmware device does not support a me= thod=0D + to report the version string of the curre= ntly=0D + stored firmware image.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve = the=0D + version string of the currently stored=0D + firmware image.=0D + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocat= e the=0D + buffer for the version string of the curr= ently=0D + stored firmware image.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetVersionString (=0D + OUT CHAR16 **VersionString=0D + )=0D +{=0D + if (VersionString =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *VersionString =3D (CHAR16 *)AllocateCopyPool (=0D + sizeof (CURRENT_FIRMWARE_VERSION_STRING),=0D + CURRENT_FIRMWARE_VERSION_STRING=0D + );=0D + if (*VersionString =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Returns the value used to fill in the Version field of the=0D + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImage= Info()=0D + service of the Firmware Management Protocol. If EFI_SUCCESS is returned= , then=0D + the firmware device supports a method to report the Version value from t= he=0D + currently stored firmware image. If the value can not be reported for t= he=0D + firmware image currently stored in the firmware device, then EFI_UNSUPPO= RTED=0D + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attem= pting=0D + to retrieve the LowestSupportedVersion value for the currently stored fi= rmware=0D + image.=0D +=0D + @note It is recommended that all firmware devices support a method to re= port=0D + the Version value from the currently stored firmware image.=0D +=0D + @param[out] Version The version value retrieved from the currently stor= ed=0D + firmware image.=0D +=0D + @retval EFI_SUCCESS The version of currently stored firmware image= was=0D + returned in Version.=0D + @retval EFI_UNSUPPORTED The firmware device does not support a method = to=0D + report the version of the currently stored fir= mware=0D + image.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the v= ersion=0D + of the currently stored firmware image.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetVersion (=0D + OUT UINT32 *Version=0D + )=0D +{=0D + *Version =3D PcdGet32 (PcdFirmwareRevision);=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Returns the value used to fill in the HardwareInstance field of the=0D + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImage= Info()=0D + service of the Firmware Management Protocol. If EFI_SUCCESS is returned= , then=0D + the firmware device supports a method to report the HardwareInstance val= ue.=0D + If the value can not be reported for the firmware device, then EFI_UNSUP= PORTED=0D + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attem= pting=0D + to retrieve the HardwareInstance value for the firmware device.=0D +=0D + @param[out] HardwareInstance The hardware instance value for the firmwa= re=0D + device.=0D +=0D + @retval EFI_SUCCESS The hardware instance for the current firmware= =0D + device is returned in HardwareInstance.=0D + @retval EFI_UNSUPPORTED The firmware device does not support a method = to=0D + report the hardware instance value.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the h= ardware=0D + instance value.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetHardwareInstance (=0D + OUT UINT64 *HardwareInstance=0D + )=0D +{=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Returns a copy of the firmware image currently stored in the firmware de= vice.=0D +=0D + @note It is recommended that all firmware devices support a method to re= trieve=0D + a copy currently stored firmware image. This can be used to suppo= rt=0D + features such as recovery and rollback.=0D +=0D + @param[out] Image Pointer to a caller allocated buffer where the= =0D + currently stored firmware image is copied to.= =0D + @param[in, out] ImageSize Pointer the size, in bytes, of the Image buffe= r.=0D + On return, points to the size, in bytes, of fi= rmware=0D + image currently stored in the firmware device.= =0D +=0D + @retval EFI_SUCCESS Image contains a copy of the firmware ima= ge=0D + currently stored in the firmware device, = and=0D + ImageSize contains the size, in bytes, of= the=0D + firmware image currently stored in the=0D + firmware device.=0D + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too = small=0D + to hold the firmware image currently stor= ed in=0D + the firmware device. The buffer size requ= ired=0D + is returned in ImageSize.=0D + @retval EFI_INVALID_PARAMETER The Image is NULL.=0D + @retval EFI_INVALID_PARAMETER The ImageSize is NULL.=0D + @retval EFI_UNSUPPORTED The operation is not supported.=0D + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve = the=0D + firmware image currently stored in the fi= rmware=0D + device.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceGetImage (=0D + OUT VOID *Image,=0D + IN OUT UINTN *ImageSize=0D + )=0D +{=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +/**=0D + Checks if a new firmware image is valid for the firmware device. This=0D + function allows firmware update operation to validate the firmware image= =0D + before FmpDeviceSetImage() is called.=0D +=0D + @param[in] Image Points to a new firmware image.=0D + @param[in] ImageSize Size, in bytes, of a new firmware image.=0D + @param[out] ImageUpdatable Indicates if a new firmware image is valid f= or=0D + a firmware update to the firmware device. T= he=0D + following values from the Firmware Managemen= t=0D + Protocol are supported:=0D + IMAGE_UPDATABLE_VALID=0D + IMAGE_UPDATABLE_INVALID=0D + IMAGE_UPDATABLE_INVALID_TYPE=0D + IMAGE_UPDATABLE_INVALID_OLD=0D + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE=0D +=0D + @retval EFI_SUCCESS The image was successfully checked. Addi= tional=0D + status information is returned in=0D + ImageUpdatable.=0D + @retval EFI_INVALID_PARAMETER Image is NULL.=0D + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceCheckImage (=0D + IN CONST VOID *Image,=0D + IN UINTN ImageSize,=0D + OUT UINT32 *ImageUpdatable=0D + )=0D +{=0D + UINT32 LastAttemptStatus;=0D +=0D + return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdatable, = &LastAttemptStatus);=0D +}=0D +=0D +/**=0D + Checks if a new firmware image is valid for the firmware device. This=0D + function allows firmware update operation to validate the firmware image= =0D + before FmpDeviceSetImage() is called.=0D +=0D + @param[in] Image Points to a new firmware image.=0D + @param[in] ImageSize Size, in bytes, of a new firmware image.= =0D + @param[out] ImageUpdatable Indicates if a new firmware image is val= id for=0D + a firmware update to the firmware device= . The=0D + following values from the Firmware Manag= ement=0D + Protocol are supported:=0D + IMAGE_UPDATABLE_VALID=0D + IMAGE_UPDATABLE_INVALID=0D + IMAGE_UPDATABLE_INVALID_TYPE=0D + IMAGE_UPDATABLE_INVALID_OLD=0D + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE= =0D + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the las= t attempt=0D + status to report back to the ESRT table = in case=0D + of error.=0D +=0D + The return status code must fall in the = range of=0D + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_E= RROR_CODE_VALUE to=0D + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_E= RROR_CODE_VALUE.=0D +=0D + If the value falls outside this range, i= t will be converted=0D + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFU= L.=0D +=0D + @retval EFI_SUCCESS The image was successfully checked. Addi= tional=0D + status information is returned in=0D + ImageUpdatable.=0D + @retval EFI_INVALID_PARAMETER Image is NULL.=0D + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceCheckImageWithStatus (=0D + IN CONST VOID *Image,=0D + IN UINTN ImageSize,=0D + OUT UINT32 *ImageUpdatable,=0D + OUT UINT32 *LastAttemptStatus=0D + )=0D +{=0D + if (LastAttemptStatus =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer= Parameter is NULL.\n"));=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS;=0D +=0D + if (ImageUpdatable =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Pa= rameter is NULL.\n"));=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CO= DE_VALUE;=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Set to valid and then if any tests fail it will update this flag.=0D + //=0D + *ImageUpdatable =3D IMAGE_UPDATABLE_VALID;=0D +=0D + if (Image =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter i= s NULL.\n"));=0D + //=0D + // Not sure if this is needed=0D + //=0D + *ImageUpdatable =3D IMAGE_UPDATABLE_INVALID;=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CO= DE_VALUE;=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Updates a firmware device with a new firmware image. This function retu= rns=0D + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware= image=0D + is updatable, the function should perform the following minimal validati= ons=0D + before proceeding to do the firmware image update.=0D + - Validate that the image is a supported image for this firmware devic= e.=0D + Return EFI_ABORTED if the image is not supported. Additional detail= s=0D + on why the image is not a supported image may be returned in AbortRe= ason.=0D + - Validate the data from VendorCode if is not NULL. Firmware image=0D + validation must be performed before VendorCode data validation.=0D + VendorCode data is ignored or considered invalid if image validation= =0D + fails. Return EFI_ABORTED if the VendorCode data is invalid.=0D +=0D + VendorCode enables vendor to implement vendor-specific firmware image up= date=0D + policy. Null if the caller did not specify the policy or use the defaul= t=0D + policy. As an example, vendor can implement a policy to allow an option= to=0D + force a firmware image update when the abort reason is due to the new fi= rmware=0D + image version is older than the current firmware image version or bad im= age=0D + checksum. Sensitive operations such as those wiping the entire firmware= image=0D + and render the device to be non-functional should be encoded in the imag= e=0D + itself rather than passed with the VendorCode. AbortReason enables vend= or to=0D + have the option to provide a more detailed description of the abort reas= on to=0D + the caller.=0D +=0D + @param[in] Image Points to the new firmware image.=0D + @param[in] ImageSize Size, in bytes, of the new firmware image.= =0D + @param[in] VendorCode This enables vendor to implement vendor-sp= ecific=0D + firmware image update policy. NULL indica= tes=0D + the caller did not specify the policy or u= se the=0D + default policy.=0D + @param[in] Progress A function used to report the progress of= =0D + updating the firmware device with the new= =0D + firmware image.=0D + @param[in] CapsuleFwVersion The version of the new firmware image from= the=0D + update capsule that provided the new firmw= are=0D + image.=0D + @param[out] AbortReason A pointer to a pointer to a Null-terminate= d=0D + Unicode string providing more details on a= n=0D + aborted operation. The buffer is allocated= by=0D + this function with=0D + EFI_BOOT_SERVICES.AllocatePool(). It is t= he=0D + caller's responsibility to free this buffe= r with=0D + EFI_BOOT_SERVICES.FreePool().=0D +=0D + @retval EFI_SUCCESS The firmware device was successfully upda= ted=0D + with the new firmware image.=0D + @retval EFI_ABORTED The operation is aborted. Additional det= ails=0D + are provided in AbortReason.=0D + @retval EFI_INVALID_PARAMETER The Image was NULL.=0D + @retval EFI_UNSUPPORTED The operation is not supported.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceSetImage (=0D + IN CONST VOID *Image,=0D + IN UINTN ImageSize,=0D + IN CONST VOID *VendorCode OP= TIONAL,=0D + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OP= TIONAL,=0D + IN UINT32 CapsuleFwVersion,=0D + OUT CHAR16 **AbortReason=0D + )=0D +{=0D + UINT32 LastAttemptStatus;=0D +=0D + return FmpDeviceSetImageWithStatus (=0D + Image,=0D + ImageSize,=0D + VendorCode,=0D + Progress,=0D + CapsuleFwVersion,=0D + AbortReason,=0D + &LastAttemptStatus=0D + );=0D +}=0D +=0D +/**=0D + Updates a firmware device with a new firmware image. This function retu= rns=0D + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware= image=0D + is updatable, the function should perform the following minimal validati= ons=0D + before proceeding to do the firmware image update.=0D + - Validate that the image is a supported image for this firmware devic= e.=0D + Return EFI_ABORTED if the image is not supported. Additional detail= s=0D + on why the image is not a supported image may be returned in AbortRe= ason.=0D + - Validate the data from VendorCode if is not NULL. Firmware image=0D + validation must be performed before VendorCode data validation.=0D + VendorCode data is ignored or considered invalid if image validation= =0D + fails. Return EFI_ABORTED if the VendorCode data is invalid.=0D +=0D + VendorCode enables vendor to implement vendor-specific firmware image up= date=0D + policy. Null if the caller did not specify the policy or use the defaul= t=0D + policy. As an example, vendor can implement a policy to allow an option= to=0D + force a firmware image update when the abort reason is due to the new fi= rmware=0D + image version is older than the current firmware image version or bad im= age=0D + checksum. Sensitive operations such as those wiping the entire firmware= image=0D + and render the device to be non-functional should be encoded in the imag= e=0D + itself rather than passed with the VendorCode. AbortReason enables vend= or to=0D + have the option to provide a more detailed description of the abort reas= on to=0D + the caller.=0D +=0D + @param[in] Image Points to the new firmware image.=0D + @param[in] ImageSize Size, in bytes, of the new firmware image.= =0D + @param[in] VendorCode This enables vendor to implement vendor-sp= ecific=0D + firmware image update policy. NULL indica= tes=0D + the caller did not specify the policy or u= se the=0D + default policy.=0D + @param[in] Progress A function used to report the progress of= =0D + updating the firmware device with the new= =0D + firmware image.=0D + @param[in] CapsuleFwVersion The version of the new firmware image from= the=0D + update capsule that provided the new firmw= are=0D + image.=0D + @param[out] AbortReason A pointer to a pointer to a Null-terminate= d=0D + Unicode string providing more details on a= n=0D + aborted operation. The buffer is allocated= by=0D + this function with=0D + EFI_BOOT_SERVICES.AllocatePool(). It is t= he=0D + caller's responsibility to free this buffe= r with=0D + EFI_BOOT_SERVICES.FreePool().=0D + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last = attempt=0D + status to report back to the ESRT table in= case=0D + of error. This value will only be checked = when this=0D + function returns an error.=0D +=0D + The return status code must fall in the ra= nge of=0D + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERR= OR_CODE_VALUE to=0D + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERR= OR_CODE_VALUE.=0D +=0D + If the value falls outside this range, it = will be converted=0D + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL.= =0D +=0D + @retval EFI_SUCCESS The firmware device was successfully upda= ted=0D + with the new firmware image.=0D + @retval EFI_ABORTED The operation is aborted. Additional det= ails=0D + are provided in AbortReason.=0D + @retval EFI_INVALID_PARAMETER The Image was NULL.=0D + @retval EFI_UNSUPPORTED The operation is not supported.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceSetImageWithStatus (=0D + IN CONST VOID *Image,=0D + IN UINTN ImageSize,=0D + IN CONST VOID *VendorCode OP= TIONAL,=0D + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OP= TIONAL,=0D + IN UINT32 CapsuleFwVersion,=0D + OUT CHAR16 **AbortReason,=0D + OUT UINT32 *LastAttemptStatus=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN Index;=0D + UPDATE_CONFIG_DATA *ConfigData;=0D + UINTN TotalSize;=0D + UINTN BytesWritten;=0D +=0D + if (Progress =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Invalid progress c= allback\n"));=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENC= IES;=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS;=0D + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %d Images ...\n", ARR= AY_SIZE (mUpdateConfigData)));=0D +=0D + //=0D + // Compute total size of update=0D + //=0D + for (Index =3D 0, TotalSize =3D 0; Index < ARRAY_SIZE (mUpdateConfigData= ); Index++) {=0D + TotalSize +=3D mUpdateConfigData[Index].Length;=0D + }=0D +=0D + BytesWritten =3D 0;=0D + for (Index =3D 0, ConfigData =3D mUpdateConfigData; Index < ARRAY_SIZE (= mUpdateConfigData); Index++, ConfigData++) {=0D + DEBUG ((=0D + DEBUG_INFO,=0D + "PlatformUpdate(%d): BaseAddress - 0x%lx ImageOffset - 0x%x Length -= 0x%x\n",=0D + Index,=0D + ConfigData->BaseAddress,=0D + ConfigData->ImageOffset,=0D + ConfigData->Length=0D + ));=0D + Status =3D PerformFlashWriteWithProgress (=0D + ConfigData->FirmwareType, = // FirmwareType=0D + ConfigData->BaseAddress, = // FlashAddress=0D + ConfigData->AddressType, = // FlashAddressType=0D + (VOID *)((UINTN)Image + (UINTN)ConfigData->ImageOffset), = // Buffer=0D + ConfigData->Length, = // BufferLength=0D + Progress, = // Progress=0D + BytesWritten / TotalSize, = // StartPercentage=0D + (BytesWritten + ConfigData->Length) * 80 / TotalSize = // EndPercentage=0D + );=0D + if (EFI_ERROR (Status)) {=0D + break;=0D + }=0D +=0D + BytesWritten +=3D ConfigData->Length;=0D + }=0D +=0D + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %r\n", Status));=0D +=0D + if (EFI_ERROR (Status)) {=0D + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CO= DE_VALUE;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Lock the firmware device that contains a firmware image. Once a firmwar= e=0D + device is locked, any attempts to modify the firmware image contents in = the=0D + firmware device must fail.=0D +=0D + @note It is recommended that all firmware devices support a lock method = to=0D + prevent modifications to a stored firmware image.=0D +=0D + @note A firmware device lock mechanism is typically only cleared by a fu= ll=0D + system reset (not just sleep state/low power mode).=0D +=0D + @retval EFI_SUCCESS The firmware device was locked.=0D + @retval EFI_UNSUPPORTED The firmware device does not support locking=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +FmpDeviceLock (=0D + VOID=0D + )=0D +{=0D + return EFI_UNSUPPORTED;=0D +}=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDevi= ceLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDevic= eLib.inf new file mode 100644 index 000000000000..abdf5d5d6ddc --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.i= nf @@ -0,0 +1,46 @@ +## @file=0D +# Provides firmware device specific services to support updates of a firm= ware=0D +# image stored in a firmware device.=0D +#=0D +# Copyright (c) 2016, Microsoft Corporation. All rights reserved.
=0D +# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
= =0D +# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 1.30=0D + BASE_NAME =3D FmpDeviceLib=0D + FILE_GUID =3D BCBACAC2-1D1D-4C14-89A3-5E27496B702D=0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D FmpDeviceLib|DXE_DRIVER UEFI_DRIVER=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 RISCV64=0D +#=0D +=0D +[Sources]=0D + FmpDeviceLib.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + FmpDevicePkg/FmpDevicePkg.dec=0D +=0D +[LibraryClasses]=0D + DebugLib=0D + BaseLib=0D + BaseMemoryLib=0D + MemoryAllocationLib=0D + PlatformFlashAccessLib=0D +=0D +[Pcd]=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision=0D + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVersion= =0D +=0D +=0D +=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessL= ib/PlatformFlashAccessLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/Pla= tformFlashAccessLib/PlatformFlashAccessLib.c new file mode 100644 index 000000000000..491757d51903 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/Plat= formFlashAccessLib.c @@ -0,0 +1,236 @@ +/** @file=0D + Platform Flash Access library.=0D +=0D + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
=0D + Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include "PlatformFlashAccessLib.h"=0D +=0D +#define ALIGN(v, a) (UINTN)((((v) - 1) | ((a) - 1)) + 1)=0D +=0D +#define FLASH_CODE_BASE 0x20000000=0D +#define FLASH_DATA_BASE 0x22000000=0D +#define FLASH_SIZE SIZE_32MB=0D +#define BLOCK_SIZE SIZE_256KB=0D +=0D +/**=0D + Perform flash write operation with progress indicator. The start and en= d=0D + completion percentage values are passed into this function. If the requ= ested=0D + flash write operation is broken up, then completion percentage between t= he=0D + start and end values may be passed to the provided Progress function. T= he=0D + caller of this function is required to call the Progress function for th= e=0D + start and end completion percentage values. This allows the Progress,=0D + StartPercentage, and EndPercentage parameters to be ignored if the reque= sted=0D + flash write operation can not be broken up=0D +=0D + @param[in] FirmwareType The type of firmware.=0D + @param[in] FlashAddress The address of flash device to be accessed.= =0D + @param[in] FlashAddressType The type of flash device address.=0D + @param[in] Buffer The pointer to the data buffer.=0D + @param[in] Length The length of data buffer in bytes.=0D + @param[in] Progress A function used report the progress of the= =0D + firmware update. This is an optional param= eter=0D + that may be NULL.=0D + @param[in] StartPercentage The start completion percentage value that = may=0D + be used to report progress during the flash= =0D + write operation.=0D + @param[in] EndPercentage The end completion percentage value that ma= y=0D + be used to report progress during the flash= =0D + write operation.=0D +=0D + @retval EFI_SUCCESS The operation returns successfully.=0D + @retval EFI_WRITE_PROTECTED The flash device is read only.=0D + @retval EFI_UNSUPPORTED The flash device access is unsupported.=0D + @retval EFI_INVALID_PARAMETER The input parameter is not valid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PerformFlashWriteWithProgress (=0D + IN PLATFORM_FIRMWARE_TYPE FirmwareType,=0D + IN EFI_PHYSICAL_ADDRESS FlashAddress,=0D + IN FLASH_ADDRESS_TYPE FlashAddressType,=0D + IN VOID *Buffer,=0D + IN UINTN Length,=0D + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL=0D + IN UINTN StartPercentage,=0D + IN UINTN EndPercentage=0D + )=0D +{=0D + EFI_STATUS Status =3D EFI_SUCCESS;=0D + UINTN LbaNum;=0D + UINTN Lba;=0D + UINTN Index;=0D + VOID *ShadowBuffer;=0D + UINTN LastBlock;=0D + UINTN NumByte;=0D + UINTN FlashBase;=0D +=0D + DEBUG ((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)Flas= hAddress, (UINTN)FlashAddressType, Length));=0D +=0D + if (FlashAddressType !=3D FlashAddressTypeAbsoluteAddress) {=0D + // Only support absolute address for this platform=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + if (FirmwareType =3D=3D PlatformFirmwareTypeSystemFirmware) {=0D + if ((FlashAddress < FLASH_CODE_BASE) || ((FlashAddress + Length) > (FL= ASH_CODE_BASE + FLASH_SIZE))) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + FlashBase =3D FLASH_CODE_BASE;=0D + } else {=0D + if ((FlashAddress < FLASH_DATA_BASE) || ((FlashAddress + Length) > (FL= ASH_DATA_BASE + FLASH_SIZE))) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + FlashBase =3D FLASH_DATA_BASE;=0D + }=0D +=0D + ShadowBuffer =3D AllocateZeroPool (BLOCK_SIZE);=0D + LastBlock =3D FLASH_SIZE / BLOCK_SIZE - 1;=0D + if ( (ALIGN (FlashAddress, BLOCK_SIZE) !=3D FlashAddress)=0D + || (Length % BLOCK_SIZE))=0D + {=0D + // Not expect un-aligned flash address=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Erase & Write=0D + //=0D + LbaNum =3D Length / BLOCK_SIZE;=0D + Lba =3D (FlashAddress - FlashBase) / BLOCK_SIZE;=0D + for (Index =3D 0; Index < LbaNum; Index++) {=0D + if (Progress !=3D NULL) {=0D + Progress (StartPercentage + ((Index * (EndPercentage - StartPercenta= ge)) / LbaNum));=0D + }=0D +=0D + if (CompareMem (=0D + (UINT8 *)(UINTN)(GET_NOR_BLOCK_ADDRESS (FlashBase, Lba + Index, = BLOCK_SIZE)),=0D + (UINT8 *)Buffer + Index * BLOCK_SIZE,=0D + BLOCK_SIZE=0D + ) =3D=3D 0)=0D + {=0D + DEBUG ((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));=0D + continue;=0D + }=0D +=0D + DEBUG ((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));=0D + NumByte =3D BLOCK_SIZE;=0D + Status =3D NorFlashWriteSingleBlock (=0D + FlashBase,=0D + FlashBase,=0D + Lba + Index,=0D + LastBlock,=0D + BLOCK_SIZE,=0D + FLASH_SIZE,=0D + 0,=0D + &NumByte,=0D + (UINT8 *)Buffer + Index * BLOCK_SIZE,=0D + ShadowBuffer=0D + );=0D + if ((Status !=3D EFI_SUCCESS) || (NumByte !=3D BLOCK_SIZE)) {=0D + DEBUG ((=0D + DEBUG_INFO,=0D + "Sector - 0x%x - update failed (bytes written)...\n",=0D + Index,=0D + NumByte=0D + ));=0D + break;=0D + }=0D + }=0D +=0D + if (Progress !=3D NULL) {=0D + Progress (EndPercentage);=0D + }=0D +=0D + FreePool (ShadowBuffer);=0D + return Status;=0D +}=0D +=0D +/**=0D + Perform flash write operation.=0D +=0D + @param[in] FirmwareType The type of firmware.=0D + @param[in] FlashAddress The address of flash device to be accessed.= =0D + @param[in] FlashAddressType The type of flash device address.=0D + @param[in] Buffer The pointer to the data buffer.=0D + @param[in] Length The length of data buffer in bytes.=0D +=0D + @retval EFI_SUCCESS The operation returns successfully.=0D + @retval EFI_WRITE_PROTECTED The flash device is read only.=0D + @retval EFI_UNSUPPORTED The flash device access is unsupported.=0D + @retval EFI_INVALID_PARAMETER The input parameter is not valid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PerformFlashWrite (=0D + IN PLATFORM_FIRMWARE_TYPE FirmwareType,=0D + IN EFI_PHYSICAL_ADDRESS FlashAddress,=0D + IN FLASH_ADDRESS_TYPE FlashAddressType,=0D + IN VOID *Buffer,=0D + IN UINTN Length=0D + )=0D +{=0D + return PerformFlashWriteWithProgress (=0D + FirmwareType,=0D + FlashAddress,=0D + FlashAddressType,=0D + Buffer,=0D + Length,=0D + NULL,=0D + 0,=0D + 0=0D + );=0D +}=0D +=0D +/**=0D + Platform Flash Access Lib Constructor.=0D +=0D + @param[in] ImageHandle The firmware allocated handle for the EFI = image.=0D + @param[in] SystemTable A pointer to the EFI System Table.=0D +=0D + @retval EFI_SUCCESS Constructor returns successfully.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PlatformFlashAccessLibConstructor (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + //=0D + // map the code flash region, the data flash region=0D + // already mapped via variable driver=0D + //=0D + Status =3D gDS->AddMemorySpace (=0D + EfiGcdMemoryTypeMemoryMappedIo,=0D + FLASH_CODE_BASE,=0D + SIZE_32MB,=0D + EFI_MEMORY_UC=0D + );=0D + if (!EFI_ERROR (Status)) {=0D + Status =3D gDS->SetMemorySpaceAttributes (=0D + FLASH_CODE_BASE,=0D + SIZE_32MB,=0D + EFI_MEMORY_UC=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessL= ib/PlatformFlashAccessLib.h b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/Pla= tformFlashAccessLib/PlatformFlashAccessLib.h new file mode 100644 index 000000000000..fe3cf0a17b3c --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/Plat= formFlashAccessLib.h @@ -0,0 +1,95 @@ +/** @file=0D + Platform flash device access library.=0D +=0D + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __PLATFORM_FLASH_ACCESS_LIB_H__=0D +#define __PLATFORM_FLASH_ACCESS_LIB_H__=0D +=0D +#include =0D +=0D +typedef enum {=0D + FlashAddressTypeRelativeAddress,=0D + FlashAddressTypeAbsoluteAddress,=0D +} FLASH_ADDRESS_TYPE;=0D +=0D +//=0D +// Type 0 ~ 0x7FFFFFFF is defined in this library.=0D +// Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM.=0D +//=0D +typedef enum {=0D + PlatformFirmwareTypeSystemFirmware,=0D + PlatformFirmwareTypeNvRam,=0D +} PLATFORM_FIRMWARE_TYPE;=0D +=0D +/**=0D + Perform flash write operation.=0D +=0D + @param[in] FirmwareType The type of firmware.=0D + @param[in] FlashAddress The address of flash device to be accessed.= =0D + @param[in] FlashAddressType The type of flash device address.=0D + @param[in] Buffer The pointer to the data buffer.=0D + @param[in] Length The length of data buffer in bytes.=0D +=0D + @retval EFI_SUCCESS The operation returns successfully.=0D + @retval EFI_WRITE_PROTECTED The flash device is read only.=0D + @retval EFI_UNSUPPORTED The flash device access is unsupported.=0D + @retval EFI_INVALID_PARAMETER The input parameter is not valid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PerformFlashWrite (=0D + IN PLATFORM_FIRMWARE_TYPE FirmwareType,=0D + IN EFI_PHYSICAL_ADDRESS FlashAddress,=0D + IN FLASH_ADDRESS_TYPE FlashAddressType,=0D + IN VOID *Buffer,=0D + IN UINTN Length=0D + );=0D +=0D +/**=0D + Perform flash write operation with progress indicator. The start and en= d=0D + completion percentage values are passed into this function. If the requ= ested=0D + flash write operation is broken up, then completion percentage between t= he=0D + start and end values may be passed to the provided Progress function. T= he=0D + caller of this function is required to call the Progress function for th= e=0D + start and end completion percentage values. This allows the Progress,=0D + StartPercentage, and EndPercentage parameters to be ignored if the reque= sted=0D + flash write operation can not be broken up=0D +=0D + @param[in] FirmwareType The type of firmware.=0D + @param[in] FlashAddress The address of flash device to be accessed.= =0D + @param[in] FlashAddressType The type of flash device address.=0D + @param[in] Buffer The pointer to the data buffer.=0D + @param[in] Length The length of data buffer in bytes.=0D + @param[in] Progress A function used report the progress of the= =0D + firmware update. This is an optional param= eter=0D + that may be NULL.=0D + @param[in] StartPercentage The start completion percentage value that = may=0D + be used to report progress during the flash= =0D + write operation.=0D + @param[in] EndPercentage The end completion percentage value that ma= y=0D + be used to report progress during the flash= =0D + write operation.=0D +=0D + @retval EFI_SUCCESS The operation returns successfully.=0D + @retval EFI_WRITE_PROTECTED The flash device is read only.=0D + @retval EFI_UNSUPPORTED The flash device access is unsupported.=0D + @retval EFI_INVALID_PARAMETER The input parameter is not valid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PerformFlashWriteWithProgress (=0D + IN PLATFORM_FIRMWARE_TYPE FirmwareType,=0D + IN EFI_PHYSICAL_ADDRESS FlashAddress,=0D + IN FLASH_ADDRESS_TYPE FlashAddressType,=0D + IN VOID *Buffer,=0D + IN UINTN Length,=0D + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIO= NAL,=0D + IN UINTN StartPercentage,=0D + IN UINTN EndPercentage=0D + );=0D +=0D +#endif=0D diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessL= ib/PlatformFlashAccessLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/P= latformFlashAccessLib/PlatformFlashAccessLib.inf new file mode 100644 index 000000000000..1c632f2fde52 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/Plat= formFlashAccessLib.inf @@ -0,0 +1,34 @@ +## @file=0D +# Platform Flash Access library.=0D +#=0D +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
= =0D +# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 1.30=0D + BASE_NAME =3D PlatformFlashAccessLibDxe=0D + FILE_GUID =3D 2FDAFAFE-0179-4047-90A4-40BC56CFBBAE= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D PlatformFlashAccessLib=0D + CONSTRUCTOR =3D PlatformFlashAccessLibConstructor=0D +=0D +[Sources]=0D + PlatformFlashAccessLib.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseMemoryLib=0D + PcdLib=0D + DebugLib=0D + VirtNorFlashDeviceLib=0D + UefiBootServicesTableLib=0D + DxeServicesTableLib=0D diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVV= irtQemu.dsc index 8e864e123f08..47e388ced4a2 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc +++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc @@ -56,10 +56,20 @@ !error "NETWORK_SNP_ENABLE is IA32/X64/EBC only"=0D !endif=0D =0D + #=0D + # UPDATE/RECOVERY definition=0D + #=0D + DEFINE CAPSULE_ENABLE =3D FALSE=0D + DEFINE FMP_SYSTEM_DEVICE =3D BCBACAC2-1D1D-4C14-89A3-5E27496B702D= =0D =0D !include MdePkg/MdeLibs.dsc.inc=0D !include NetworkPkg/Network.dsc.inc=0D =0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D + POSTBUILD =3D python OvmfPkg/RiscVVirt/Feature/Caps= ule/GenerateCapsule/GenCapsule.py=0D +!include OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc=0D +!endif=0D +=0D [BuildOptions]=0D GCC:RELEASE_*_*_CC_FLAGS =3D -DMDEPKG_NDEBUG=0D !ifdef $(SOURCE_DEBUG_ENABLE)=0D @@ -118,6 +128,18 @@ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLi= bNull/PeiDxeTpmPlatformHierarchyLib.inf=0D !endif=0D =0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf=0D + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.i= nf=0D + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf=0D + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf=0D + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf=0D + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf=0D + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAu= thenticationLibPkcs7.inf=0D + DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibTe= xt/DisplayUpdateProgressLibText.inf=0D + RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf=0D +!endif=0D +=0D [LibraryClasses.common.DXE_DRIVER]=0D AcpiPlatformLib|OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf=0D ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeRepor= tStatusCodeLib.inf=0D @@ -131,6 +153,11 @@ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf=0D PciExpressLib|OvmfPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExp= ressLib.inf=0D =0D +[LibraryClasses.common.DXE_RUNTIME_DRIVER]=0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.in= f=0D +!endif=0D +=0D ##########################################################################= ######=0D #=0D # Pcd Section - list of all EDK II PCD Entries defined by this Platform.=0D @@ -230,6 +257,10 @@ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0=0D !endif=0D =0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid|{GUID(= "$(FMP_SYSTEM_DEVICE)")}|VOID*|0x10=0D +!endif=0D +=0D [PcdsDynamicHii]=0D gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGu= id|0x0|FALSE|NV,BS=0D =0D @@ -493,3 +524,11 @@ =0D NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf=0D }=0D +=0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D + MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf=0D + MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf {=0D + =0D + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D + }=0D +!endif=0D diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf b/OvmfPkg/RiscVVirt/RiscVV= irtQemu.fdf index 4528a44d3b82..8cbd5711aa64 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf +++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf @@ -216,6 +216,11 @@ INF MdeModulePkg/Logo/LogoDxe.inf #=0D INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf=0D =0D +!if $(CAPSULE_ENABLE) =3D=3D TRUE=0D +INF MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf=0D +INF FILE_GUID =3D $(FMP_SYSTEM_DEVICE) FmpDevicePkg/FmpDxe/FmpDxe.inf=0D +!endif=0D +=0D ##########################################################################= ######=0D =0D [FV.FVMAIN_COMPACT]=0D diff --git a/OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc b/OvmfPkg/RiscVVir= t/RiscVVirtSystemFW.dsc.inc new file mode 100644 index 000000000000..644e894e03fc --- /dev/null +++ b/OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc @@ -0,0 +1,61 @@ +## @file=0D +# FmpDxe driver for system firmware update.=0D +#=0D +# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +FmpDevicePkg/FmpDxe/FmpDxe.inf {=0D + =0D + #=0D + # ESRT and FMP GUID for system device capsule update=0D + #=0D + FILE_GUID =3D $(FMP_SYSTEM_DEVICE)=0D +=0D + =0D + #=0D + # Unicode name string that is used to populate FMP Image Descriptor = for this capsule update module=0D + #=0D + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceImageIdName|L"RISC-V VIRT Sy= stem Firmware Device"=0D +=0D + #=0D + # ESRT and FMP Lowest Support Version for this capsule update module= =0D + # 000.000.000.000=0D + #=0D + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVers= ion|0x00000001=0D +=0D + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressWatchdogTimeInSecond= s|2=0D +=0D + #=0D + # Capsule Update Progress Bar Color. Set to Green (RGB) (0, 255, 0)= =0D + #=0D + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressColor|0x0000FF00=0D +=0D + #=0D + # Certificates used to authenticate capsule update image=0D + # EDKII Test certificate=0D + #=0D + !include BaseTools/Source/Python/Pkcs7Sign/TestRoot.cer.gFmpDevicePk= gTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr.inc=0D +=0D + =0D + #=0D + # Generic libraries that are used "as is" by all FMP modules=0D + #=0D + FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPa= yloadHeaderLibV1.inf=0D + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/F= mpAuthenticationLibPkcs7.inf=0D + FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependency= Lib.inf=0D + FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLibNull= /FmpDependencyCheckLibNull.inf=0D + FmpDependencyDeviceLib|FmpDevicePkg/Library/FmpDependencyDeviceLibNu= ll/FmpDependencyDeviceLibNull.inf=0D + #=0D + # Platform specific capsule policy library=0D + #=0D + CapsuleUpdatePolicyLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/Cap= suleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf=0D + #=0D + # Device specific library that processes a capsule and updates the F= W storage device=0D + #=0D + FmpDeviceLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/= FmpDeviceLib.inf=0D + VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorF= lashDeviceLib.inf=0D + PlatformFlashAccessLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/Pla= tformFlashAccessLib/PlatformFlashAccessLib.inf=0D + }=0D --=20 2.34.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#121278): https://edk2.groups.io/g/devel/message/121278 Mute This Topic: https://groups.io/mt/112379040/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-