From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR04-HE1-obe.outbound.protection.outlook.com (EUR04-HE1-obe.outbound.protection.outlook.com [40.107.7.72]) by mx.groups.io with SMTP id smtpd.web10.22515.1669132016693709834 for ; Tue, 22 Nov 2022 07:46:57 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@armh.onmicrosoft.com header.s=selector2-armh-onmicrosoft-com header.b=6l5kgm8d; spf=pass (domain: arm.com, ip: 40.107.7.72, mailfrom: sami.mujawar@arm.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=EyOXggk/MeCy325Wb5vCwK4mXwzNrcYCry6UvHRin6U=; b=6l5kgm8dSqXyluFVriUv4CBiGfvl3jvb0DKxm2HFQWorJqzMAE/1wt9Vb7AOBgGev9c2MO8BQN4ppnKKu4GjnLKRr/DSUgY06YdYmM6AQESWgG5o1DNZqQGzjQPEn5sSW7F+GEnEaXC2rrp7aRr4e1bQhNcyw/GEyYD0X6Fyb7M= Received: from DBBPR09CA0034.eurprd09.prod.outlook.com (2603:10a6:10:d4::22) by AS8PR08MB9069.eurprd08.prod.outlook.com (2603:10a6:20b:5b1::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5857.17; Tue, 22 Nov 2022 15:46:52 +0000 Received: from DBAEUR03FT006.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:d4:cafe::87) by DBBPR09CA0034.outlook.office365.com (2603:10a6:10:d4::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5834.15 via Frontend Transport; Tue, 22 Nov 2022 15:46:52 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DBAEUR03FT006.mail.protection.outlook.com (100.127.142.72) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5834.8 via Frontend Transport; Tue, 22 Nov 2022 15:46:52 +0000 Received: ("Tessian outbound aeae1c7b66fd:v130"); Tue, 22 Nov 2022 15:46:52 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 6843606cdae919e9 X-CR-MTA-TID: 64aa7808 Received: from 5a75ef615009.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 5309D648-E564-49FB-A193-F76365E9660A.1; Tue, 22 Nov 2022 15:46:43 +0000 Received: from EUR03-DBA-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 5a75ef615009.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Tue, 22 Nov 2022 15:46:43 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JFAyXAdHjfIqdBjAx+emuHEvDBHAhF25ocVGOwJDaVMX8aZMIB159rc7oAOU1MKZutGX/ofkzp9q568dIUFGANpAw2uBLRDXOaFQVT3bglzgGciNZB91Pnu5S7JEAn3WWKOod2JGfjrSoO2QENKMd8f/jxFMdfrVkmdOEZwk6SIR0ET+MlagC2nn9RLWruNJ4WzAathV6tRwpjk9+QXfk/4fGR2a2phTjDEmMARAT8NmV4qen3178Lv2krWOz2nzpwT75brd+pGGDGbvr8HlrB9O5k10thNBAXWpzCc+veploPJzs92bIXia9LmLNrLdCKEdBl8aL1FjymgE0VFGaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=EyOXggk/MeCy325Wb5vCwK4mXwzNrcYCry6UvHRin6U=; b=hiXmjS8ku8UjfLIOjak+Md74E+C2tZDCFfx4/Amp4cLOzLNWYhvJl98JtMJ5NyffsgZ0oVGfcUBg4IpaA43nlbMmE0q8iF1wmTnVfpjxSsmO7ewLNvoGk4bcoMVxqsrCAxXQcFzeJDKTfof2gV3LN0DXlxQFZAXJSXodKM7EYlP7c2uYdz3nkpfWq5KIpTH45YVnXn80/jUvC3+1iZhbD8+zmvRN+rG9TZeQDRjX7LBIEOmq5uHA9CIgflvI0cOUgH+xgd/MkKY/O5USEdNzgKGhYeXIAo4nImSihiPc/F1mOs7+2gORHKvjSOdhb3jZYQ/2qIxw9pkvCR1gjF4JnA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=EyOXggk/MeCy325Wb5vCwK4mXwzNrcYCry6UvHRin6U=; b=6l5kgm8dSqXyluFVriUv4CBiGfvl3jvb0DKxm2HFQWorJqzMAE/1wt9Vb7AOBgGev9c2MO8BQN4ppnKKu4GjnLKRr/DSUgY06YdYmM6AQESWgG5o1DNZqQGzjQPEn5sSW7F+GEnEaXC2rrp7aRr4e1bQhNcyw/GEyYD0X6Fyb7M= Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Received: from AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) by PAXPR08MB6605.eurprd08.prod.outlook.com (2603:10a6:102:153::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5857.17; Tue, 22 Nov 2022 15:46:37 +0000 Received: from AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::eca2:349c:4dbf:7f10]) by AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::eca2:349c:4dbf:7f10%9]) with mapi id 15.20.5857.017; Tue, 22 Nov 2022 15:46:37 +0000 Message-ID: <3bda482a-8fb7-0e05-1413-bd87b9112bc8@arm.com> Date: Tue, 22 Nov 2022 15:46:35 +0000 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.5.0 Subject: Re: [PATCH 1/3] CloudHv:arm: add kernel load fs driver To: Jianyong Wu , devel@edk2.groups.io Cc: ardb+tianocore@kernel.org, justin.he@arm.com, "nd@arm.com" References: <20220916024620.114084-1-jianyong.wu@arm.com> <20220916024620.114084-2-jianyong.wu@arm.com> From: "Sami Mujawar" In-Reply-To: <20220916024620.114084-2-jianyong.wu@arm.com> X-ClientProxiedBy: LO4P302CA0045.GBRP302.PROD.OUTLOOK.COM (2603:10a6:600:317::20) To AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: AS8PR08MB6806:EE_|PAXPR08MB6605:EE_|DBAEUR03FT006:EE_|AS8PR08MB9069:EE_ X-MS-Office365-Filtering-Correlation-Id: 9d49f1be-735d-43b1-346e-08dacca0c6c1 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: heNLZ7gTZE3qUIwvfNXqEiJALGxCkMGhEF+xaGNGHP+vLpY58JKdRdsLyHWi338sMX2+sFBia4bVRWn18aF9wk5578Q6whvutBcwcAe0/nXr90Qgw7WfJzoGZLFF/hRwzhZAK3Lr2vxQQrttechh9kdluQ+1SdWgP/GXXE9rzlfHtssy1RSCZnJW/I9HoUZU4XjdM5XWJEuJzIynPImlYhHufIEqqddUOTjZjJ3ATRT7CnY+eoWeaft1tfBHyZL4yQRJ7PwwyVr/iO/VkX3NaMJu/8qVD9d2ZvY3NyDLreB/r6yNjDg629aIjt7DzW3ik8HZBqgOi0QBeXLqs1UUvOxoVHkF2j3Ztb7H1zywaU3P5hNIT+1j7gUaS2Y3kkv5bmUVNMk9UG7viVtCiN4MNgVegtR+9gDRM2A/OUxBKKIcX7wLpDsXIaFXefFKUG2dYVV8qf//srELl4+4frokCWgTcl09EpV6KUPkJOrlb2aTNpTqieU6TzeMo7CatYb6Wogx9ro3ichOzOIPIAbSoI5HevgdSPH4LgzhFgsqHyhHoeYFWhtBRpDi6sgHDZ+mz7ItvsTo42apPxfdwL6ngLxd9Ufzv0o3NUBocDfHrzLd0eLgDRJWIxnOlC6t+ImwbPoiPY+RVC6MvGcS8bL4oAHKsuhGccb5YVDms3ZAixV2bqmV8ne/I6Z0t5TF9B5n+UlCyrbBmhdpmZpdddIxDqepPfD2E7t5mPVOpYqRO2/a9dwvpfjVgvyoJEWiPv5E X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AS8PR08MB6806.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230022)(4636009)(136003)(366004)(346002)(376002)(39860400002)(396003)(451199015)(41300700001)(8936002)(316002)(5660300002)(8676002)(66946007)(44832011)(31686004)(66476007)(30864003)(4326008)(66556008)(36756003)(6512007)(6486002)(26005)(478600001)(53546011)(19627235002)(2906002)(186003)(2616005)(6506007)(38100700002)(31696002)(83380400001)(86362001)(43740500002)(45980500001)(44824005);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR08MB6605 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; Return-Path: Sami.Mujawar@arm.com X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DBAEUR03FT006.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 2497e83c-3890-4121-cc70-08dacca0bd4e X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: gW62LqODRufTHJopK8iwgIv8LhSQdOfz9LoRKptztnDGV5ug36aLiDWLPmSbHBQM4kgSNgxvI+m1i9LuuM1Cq8dSbztXXldxoxKO2JRFN3eCQkolpR9u/AjBnWGrEVYvIuJZfy9mgkr11AUL77kfJRMcj5l7jNoKkqlbVgtop+2hZ2eF9S8LKK8Z8qCerA+sZcmKWs0C0zPapV0Aba/HKsssSIVcnGuAk0P+n00Be0xyuzZF6F4UeWoZeUUoioXj5s8eEjyZdRvxCyFB3+RhpID8bClWQUgzZE2b+sosIuXErw/TCHGKXhcNlYxFb4//A7D1tINgQDzLetSqqziKTWK7jGSioltpOWS3jhEejKwHBgaHScaFL4957CpGrFevFuWAdKxohaRS/+PKoV6v+VPtl02v+FvfnL5RjzZHl9tQHWuRHnAELVxl0b/gOzAnKxSNJ1yELaxT+y1+oZeFeel+7j3LY9kJBQ8FfBlncSY2buHoWETCtGUaaYU1spuM2lv0lCKwxPZeXtHfsG7SJZgiwOINQr8dKy1Aks3rL5nMyqPTaKGP6eroeapjbwQoARjCPS66OW7MhxSw9SAAEoPyRvWgTd5/0bjZQGQ/XCgad3FQF7qESzKA+QG15CDSm5K59/58jutGPKDHmdE5GkrYLL2lr1qih1rQa2jNzsPmV1UpVo4mV8xnS44agidLVSbQVZ9/2DT9vLnu5BKyZJxaa2Ky4c2mL/YtRBt31mW/TzV2G34BQAmTS3CZFbbg4ub18Ndw7zzSaXlFa7nuBQ== X-Forefront-Antispam-Report: CIP:63.35.35.123;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:64aa7808-outbound-1.mta.getcheckrecipient.com;PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com;CAT:NONE;SFS:(13230022)(4636009)(396003)(346002)(39860400002)(376002)(136003)(451199015)(46966006)(36840700001)(40470700004)(31686004)(6486002)(83380400001)(36860700001)(5660300002)(336012)(2616005)(40460700003)(8936002)(86362001)(40480700001)(31696002)(81166007)(36756003)(41300700001)(82740400003)(26005)(356005)(186003)(82310400005)(6512007)(4326008)(44832011)(30864003)(47076005)(478600001)(2906002)(8676002)(70586007)(316002)(6506007)(70206006)(19627235002)(53546011)(43740500002)(44824005);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2022 15:46:52.7574 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9d49f1be-735d-43b1-346e-08dacca0c6c1 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d;Ip=[63.35.35.123];Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: DBAEUR03FT006.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB9069 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi Jianyoung, I am trying to understand your patch series. Is it possible to send me the steps to test your patches using CloudHv, please? Also, please see my response for patch 2/3 as I have some queries. Regards, Sami Mujawar On 16/09/2022 03:46 am, Jianyong Wu wrote: > This is used for supporting direct kernel boot in CloudHv. CloudHv > will store kernel image in system ram and pass kernel info through > DT. It's firmware's responsibility to fetch the kernel data and > create a file device to feed for loadImage > > Signed-off-by: Jianyong Wu > --- > .../CloudHvKernelLoaderFsDxe.c | 969 ++++++++++++++++++ > .../CloudHvKernelLoaderFsDxe.inf | 56 + > 2 files changed, 1025 insertions(+) > create mode 100644 ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.c > create mode 100644 ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.inf > > diff --git a/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.c b/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.c > new file mode 100644 > index 0000000000..e4cfcfab72 > --- /dev/null > +++ b/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.c > @@ -0,0 +1,969 @@ > +/** @file > + DXE driver to expose the 'kernel', 'initrd' and 'cmdline' blobs > + provided by Cloud Hypervisor as files in an abstract file system > + > + Copyright (C) 2022, Arm, Limited. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// > +// Static data that hosts the data blobs and serves file requests. > +// > +typedef enum { > + KernelBlobTypeKernel, > + KernelBlobTypeInitrd, > + KernelBlobTypeCommandLine, > + KernelBlobTypeMax > +} KERNEL_BLOB_TYPE; > + > +typedef struct { > + CONST CHAR16 Name[8]; > + UINT32 Size; > + UINT8 *Data; > +} KERNEL_BLOB; > + > +STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = { > + { > + L"kernel", > + },{ > + L"initrd", > + },{ > + L"cmdline", > + } > +}; > + > +// > +// Device path for the handle that incorporates our "EFI stub filesystem". > +// > +#pragma pack (1) > +typedef struct { > + VENDOR_DEVICE_PATH VenMediaNode; > + EFI_DEVICE_PATH_PROTOCOL EndNode; > +} SINGLE_VENMEDIA_NODE_DEVPATH; > +#pragma pack () > + > +STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mFileSystemDevicePath = { > + { > + { > + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, > + { sizeof (VENDOR_DEVICE_PATH) } > + }, > + QEMU_KERNEL_LOADER_FS_MEDIA_GUID > + }, { > + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { sizeof (EFI_DEVICE_PATH_PROTOCOL) } > + } > +}; > + > +STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mInitrdDevicePath = { > + { > + { > + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, > + { sizeof (VENDOR_DEVICE_PATH) } > + }, > + LINUX_EFI_INITRD_MEDIA_GUID > + }, { > + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { sizeof (EFI_DEVICE_PATH_PROTOCOL) } > + } > +}; > + > +// > +// The "file in the EFI stub filesystem" abstraction. > +// > +STATIC EFI_TIME mInitTime; > +STATIC UINT64 mTotalBlobBytes; > + > +#define STUB_FILE_SIG SIGNATURE_64 ('S', 'T', 'U', 'B', 'F', 'I', 'L', 'E') > + > +typedef struct { > + UINT64 Signature; // Carries STUB_FILE_SIG. > + > + KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax > + // denotes the root directory of the filesystem. > + > + UINT64 Position; // Byte position for regular files; > + // next directory entry to return for the root > + // directory. > + > + EFI_FILE_PROTOCOL File; // Standard protocol interface. > +} STUB_FILE; > + > +#define STUB_FILE_FROM_FILE(FilePointer) \ > + CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG) > + > +/** > + Helper function that formats an EFI_FILE_INFO structure into the > + user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including > + KernelBlobTypeMax, which stands for the root directory). > + > + The interface follows the EFI_FILE_GET_INFO -- and for directories, the > + EFI_FILE_READ -- interfaces. > + > + @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg > + blob backing the STUB_FILE that information is > + being requested about. If BlobType equals > + KernelBlobTypeMax, then information will be > + provided about the root directory of the > + filesystem. > + > + @param[in,out] BufferSize On input, the size of Buffer. On output, the > + amount of data returned in Buffer. In both cases, > + the size is measured in bytes. > + > + @param[out] Buffer A pointer to the data buffer to return. The > + buffer's type is EFI_FILE_INFO. > + > + @retval EFI_SUCCESS The information was returned. > + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to store the > + EFI_FILE_INFO structure. BufferSize has been > + updated with the size needed to complete the > + request. > +**/ > +EFI_STATUS > +ConvertKernelBlobTypeToFileInfo ( > + IN KERNEL_BLOB_TYPE BlobType, > + IN OUT UINTN *BufferSize, > + OUT VOID *Buffer > + ) > +{ > + CONST CHAR16 *Name; > + UINT64 FileSize; > + UINT64 Attribute; > + > + UINTN NameSize; > + UINTN FileInfoSize; > + EFI_FILE_INFO *FileInfo; > + UINTN OriginalBufferSize; > + > + if (BlobType == KernelBlobTypeMax) { > + // > + // getting file info about the root directory > + // > + Name = L"\\"; > + FileSize = KernelBlobTypeMax; > + Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; > + } else { > + CONST KERNEL_BLOB *Blob; > + > + Blob = &mKernelBlob[BlobType]; > + Name = Blob->Name; > + FileSize = Blob->Size; > + Attribute = EFI_FILE_READ_ONLY; > + } > + > + NameSize = (StrLen (Name) + 1) * 2; > + FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize; > + ASSERT (FileInfoSize >= sizeof *FileInfo); > + > + OriginalBufferSize = *BufferSize; > + *BufferSize = FileInfoSize; > + if (OriginalBufferSize < *BufferSize) { > + return EFI_BUFFER_TOO_SMALL; > + } > + > + FileInfo = (EFI_FILE_INFO *)Buffer; > + FileInfo->Size = FileInfoSize; > + FileInfo->FileSize = FileSize; > + FileInfo->PhysicalSize = FileSize; > + FileInfo->Attribute = Attribute; > + > + CopyMem (&FileInfo->CreateTime, &mInitTime, sizeof mInitTime); > + CopyMem (&FileInfo->LastAccessTime, &mInitTime, sizeof mInitTime); > + CopyMem (&FileInfo->ModificationTime, &mInitTime, sizeof mInitTime); > + CopyMem (FileInfo->FileName, Name, NameSize); > + > + return EFI_SUCCESS; > +} > + > +/** > + Reads data from a file, or continues scanning a directory. > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that > + is the file handle to read data from. > + > + @param[in,out] BufferSize On input, the size of the Buffer. On output, the > + amount of data returned in Buffer. In both cases, > + the size is measured in bytes. If the read goes > + beyond the end of the file, the read length is > + truncated to the end of the file. > + > + If This is a directory, the function reads the > + directory entry at the current position and > + returns the entry (as EFI_FILE_INFO) in Buffer. If > + there are no more directory entries, the > + BufferSize is set to zero on output. > + > + @param[out] Buffer The buffer into which the data is read. > + > + @retval EFI_SUCCESS Data was read. > + @retval EFI_NO_MEDIA The device has no medium. > + @retval EFI_DEVICE_ERROR The device reported an error. > + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted > + file. > + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond > + the end of the file. > + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the > + current directory entry as a EFI_FILE_INFO > + structure. BufferSize has been updated with the > + size needed to complete the request, and the > + directory position has not been advanced. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileRead ( > + IN EFI_FILE_PROTOCOL *This, > + IN OUT UINTN *BufferSize, > + OUT VOID *Buffer > + ) > +{ > + STUB_FILE *StubFile; > + CONST KERNEL_BLOB *Blob; > + UINT64 Left; > + > + StubFile = STUB_FILE_FROM_FILE (This); > + > + // > + // Scanning the root directory? > + // > + if (StubFile->BlobType == KernelBlobTypeMax) { > + EFI_STATUS Status; > + > + if (StubFile->Position == KernelBlobTypeMax) { > + // > + // Scanning complete. > + // > + *BufferSize = 0; > + return EFI_SUCCESS; > + } > + > + Status = ConvertKernelBlobTypeToFileInfo ( > + (KERNEL_BLOB_TYPE)StubFile->Position, > + BufferSize, > + Buffer > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ++StubFile->Position; > + return EFI_SUCCESS; > + } > + > + // > + // Reading a file. > + // > + Blob = &mKernelBlob[StubFile->BlobType]; > + if (StubFile->Position > Blob->Size) { > + return EFI_DEVICE_ERROR; > + } > + > + Left = Blob->Size - StubFile->Position; > + if (*BufferSize > Left) { > + *BufferSize = (UINTN)Left; > + } > + > + if (Blob->Data != NULL) { > + CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize); > + } > + > + StubFile->Position += *BufferSize; > + return EFI_SUCCESS; > +} > + > +/** > + Closes a specified file handle. > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file > + handle to close. > + > + @retval EFI_SUCCESS The file was closed. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileClose ( > + IN EFI_FILE_PROTOCOL *This > + ) > +{ > + FreePool (STUB_FILE_FROM_FILE (This)); > + return EFI_SUCCESS; > +} > + > +/** > + Close and delete the file handle. > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the > + handle to the file to delete. > + > + @retval EFI_SUCCESS The file was closed and deleted, and the > + handle was closed. > + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not > + deleted. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileDelete ( > + IN EFI_FILE_PROTOCOL *This > + ) > +{ > + FreePool (STUB_FILE_FROM_FILE (This)); > + return EFI_WARN_DELETE_FAILURE; > +} > + > +// > +// Protocol member functions for File. > +// > + > +/** > + Opens a new file relative to the source file's location. > + > + (Forward declaration.) > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is > + the file handle to the source location. This would > + typically be an open handle to a directory. > + > + @param[out] NewHandle A pointer to the location to return the opened handle > + for the new file. > + > + @param[in] FileName The Null-terminated string of the name of the file to > + be opened. The file name may contain the following > + path modifiers: "\", ".", and "..". > + > + @param[in] OpenMode The mode to open the file. The only valid > + combinations that the file may be opened with are: > + Read, Read/Write, or Create/Read/Write. > + > + @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case > + these are the attribute bits for the newly created > + file. > + > + @retval EFI_SUCCESS The file was opened. > + @retval EFI_NOT_FOUND The specified file could not be found on the > + device. > + @retval EFI_NO_MEDIA The device has no medium. > + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the > + medium is no longer supported. > + @retval EFI_DEVICE_ERROR The device reported an error. > + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a > + file for write when the media is > + write-protected. > + @retval EFI_ACCESS_DENIED The service denied access to the file. > + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the > + file. > + @retval EFI_VOLUME_FULL The volume is full. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileOpen ( > + IN EFI_FILE_PROTOCOL *This, > + OUT EFI_FILE_PROTOCOL **NewHandle, > + IN CHAR16 *FileName, > + IN UINT64 OpenMode, > + IN UINT64 Attributes > + ); > + > +/** > + Returns information about a file. > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance > + that is the file handle the requested > + information is for. > + > + @param[in] InformationType The type identifier GUID for the information > + being requested. The following information > + types are supported, storing the > + corresponding structures in Buffer: > + > + - gEfiFileInfoGuid: EFI_FILE_INFO > + > + - gEfiFileSystemInfoGuid: > + EFI_FILE_SYSTEM_INFO > + > + - gEfiFileSystemVolumeLabelInfoIdGuid: > + EFI_FILE_SYSTEM_VOLUME_LABEL > + > + @param[in,out] BufferSize On input, the size of Buffer. On output, the > + amount of data returned in Buffer. In both > + cases, the size is measured in bytes. > + > + @param[out] Buffer A pointer to the data buffer to return. The > + buffer's type is indicated by > + InformationType. > + > + @retval EFI_SUCCESS The information was returned. > + @retval EFI_UNSUPPORTED The InformationType is not known. > + @retval EFI_NO_MEDIA The device has no medium. > + @retval EFI_DEVICE_ERROR The device reported an error. > + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the > + information structure requested by > + InformationType. BufferSize has been updated > + with the size needed to complete the request. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileGetInfo ( > + IN EFI_FILE_PROTOCOL *This, > + IN EFI_GUID *InformationType, > + IN OUT UINTN *BufferSize, > + OUT VOID *Buffer > + ) > +{ > + CONST STUB_FILE *StubFile; > + UINTN OriginalBufferSize; > + > + StubFile = STUB_FILE_FROM_FILE (This); > + > + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { > + return ConvertKernelBlobTypeToFileInfo ( > + StubFile->BlobType, > + BufferSize, > + Buffer > + ); > + } > + > + OriginalBufferSize = *BufferSize; > + > + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { > + EFI_FILE_SYSTEM_INFO *FileSystemInfo; > + > + *BufferSize = sizeof *FileSystemInfo; > + if (OriginalBufferSize < *BufferSize) { > + return EFI_BUFFER_TOO_SMALL; > + } > + > + FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer; > + FileSystemInfo->Size = sizeof *FileSystemInfo; > + FileSystemInfo->ReadOnly = TRUE; > + FileSystemInfo->VolumeSize = mTotalBlobBytes; > + FileSystemInfo->FreeSpace = 0; > + FileSystemInfo->BlockSize = 1; > + FileSystemInfo->VolumeLabel[0] = L'\0'; > + > + return EFI_SUCCESS; > + } > + > + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { > + EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel; > + > + *BufferSize = sizeof *FileSystemVolumeLabel; > + if (OriginalBufferSize < *BufferSize) { > + return EFI_BUFFER_TOO_SMALL; > + } > + > + FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer; > + FileSystemVolumeLabel->VolumeLabel[0] = L'\0'; > + > + return EFI_SUCCESS; > + } > + > + return EFI_UNSUPPORTED; > +} > + > +// > +// External definition of the file protocol template. > +// > +STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = { > + EFI_FILE_PROTOCOL_REVISION, // revision 1 > + StubFileOpen, > + StubFileClose, > + StubFileDelete, > + StubFileRead, > + NULL, > + NULL, > + NULL, > + StubFileGetInfo, > + NULL, > + NULL, > + NULL, // OpenEx, revision 2 > + NULL, // ReadEx, revision 2 > + NULL, // WriteEx, revision 2 > + NULL // FlushEx, revision 2 > +}; > + > +/** > + Opens a new file relative to the source file's location. > + > + (Forward declaration.) > + > + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is > + the file handle to the source location. This would > + typically be an open handle to a directory. > + > + @param[out] NewHandle A pointer to the location to return the opened handle > + for the new file. > + > + @param[in] FileName The Null-terminated string of the name of the file to > + be opened. The file name may contain the following > + path modifiers: "\", ".", and "..". > + > + @param[in] OpenMode The mode to open the file. The only valid > + combinations that the file may be opened with are: > + Read, Read/Write, or Create/Read/Write. > + > + @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case > + these are the attribute bits for the newly created > + file. > + > + @retval EFI_SUCCESS The file was opened. > + @retval EFI_NOT_FOUND The specified file could not be found on the > + device. > + @retval EFI_NO_MEDIA The device has no medium. > + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the > + medium is no longer supported. > + @retval EFI_DEVICE_ERROR The device reported an error. > + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a > + file for write when the media is > + write-protected. > + @retval EFI_ACCESS_DENIED The service denied access to the file. > + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the > + file. > + @retval EFI_VOLUME_FULL The volume is full. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileOpen ( > + IN EFI_FILE_PROTOCOL *This, > + OUT EFI_FILE_PROTOCOL **NewHandle, > + IN CHAR16 *FileName, > + IN UINT64 OpenMode, > + IN UINT64 Attributes > + ) > +{ > + CONST STUB_FILE *StubFile; > + UINTN BlobType; > + STUB_FILE *NewStubFile; > + > + // > + // We're read-only. > + // > + switch (OpenMode) { > + case EFI_FILE_MODE_READ: > + break; > + > + case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: > + case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE: > + return EFI_WRITE_PROTECTED; > + > + default: > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Only the root directory supports opening files in it. > + // > + StubFile = STUB_FILE_FROM_FILE (This); > + if (StubFile->BlobType != KernelBlobTypeMax) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Locate the file. > + // > + for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { > + if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) { > + break; > + } > + } > + > + if (BlobType == KernelBlobTypeMax) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Found it. > + // > + NewStubFile = AllocatePool (sizeof *NewStubFile); > + if (NewStubFile == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + NewStubFile->Signature = STUB_FILE_SIG; > + NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType; > + NewStubFile->Position = 0; > + CopyMem ( > + &NewStubFile->File, > + &mEfiFileProtocolTemplate, > + sizeof mEfiFileProtocolTemplate > + ); > + *NewHandle = &NewStubFile->File; > + > + return EFI_SUCCESS; > +} > + > +// > +// Protocol member functions for SimpleFileSystem. > +// > + > +/** > + Open the root directory on a volume. > + > + @param[in] This A pointer to the volume to open the root directory on. > + > + @param[out] Root A pointer to the location to return the opened file handle > + for the root directory in. > + > + @retval EFI_SUCCESS The device was opened. > + @retval EFI_UNSUPPORTED This volume does not support the requested file > + system type. > + @retval EFI_NO_MEDIA The device has no medium. > + @retval EFI_DEVICE_ERROR The device reported an error. > + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > + @retval EFI_ACCESS_DENIED The service denied access to the file. > + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of > + resources. > + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the > + medium is no longer supported. Any existing > + file handles for this volume are no longer > + valid. To access the files on the new medium, > + the volume must be reopened with OpenVolume(). > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +StubFileSystemOpenVolume ( > + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, > + OUT EFI_FILE_PROTOCOL **Root > + ) > +{ > + STUB_FILE *StubFile; > + > + StubFile = AllocatePool (sizeof *StubFile); > + if (StubFile == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + StubFile->Signature = STUB_FILE_SIG; > + StubFile->BlobType = KernelBlobTypeMax; > + StubFile->Position = 0; > + CopyMem ( > + &StubFile->File, > + &mEfiFileProtocolTemplate, > + sizeof mEfiFileProtocolTemplate > + ); > + *Root = &StubFile->File; > + > + return EFI_SUCCESS; > +} > + > +STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = { > + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, > + StubFileSystemOpenVolume > +}; > + > +/** > + Load initrd data to memory > + > + @param[in] This Not used here. > + @param[in] FilePath Contain some metadata of file device where holds the initrd. > + @param[in] BootPolicy Not support here. > + @param[in,out] BufferSize On input, contains the memory buff size. > + On output, contains the initrd blob size. > + @param[out] Buffer A pointer point to memory which contains initrd data. > + > + @retval EFI_UNSUPPORTED Once the Boot Policy is true. > + @retval EFI_INVALID_PARAMETER Once there is no BuffSize given or no available file device. > + @retval EFI_NOT_FOUND File path doesn't match. > + @retval EFI_BUFFER_TOO_SMALL Buff size too small. > + @retval EFI_SUCCESS Success. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +InitrdLoadFile2 ( > + IN EFI_LOAD_FILE2_PROTOCOL *This, > + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, > + IN BOOLEAN BootPolicy, > + IN OUT UINTN *BufferSize, > + OUT VOID *Buffer OPTIONAL > + ) > +{ > + CONST KERNEL_BLOB *InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd]; > + > + ASSERT (InitrdBlob->Size > 0); > + > + if (BootPolicy) { > + return EFI_UNSUPPORTED; > + } > + > + if ((BufferSize == NULL) || !IsDevicePathValid (FilePath, 0)) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((FilePath->Type != END_DEVICE_PATH_TYPE) || > + (FilePath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE)) > + { > + return EFI_NOT_FOUND; > + } > + > + if ((Buffer == NULL) || (*BufferSize < InitrdBlob->Size)) { > + *BufferSize = InitrdBlob->Size; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + CopyMem (Buffer, InitrdBlob->Data, InitrdBlob->Size); > + > + *BufferSize = InitrdBlob->Size; > + return EFI_SUCCESS; > +} > + > +STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = { > + InitrdLoadFile2, > +}; > + > +/** > + Fetch kernel, initrd and commandline into Blob. > + > + @param Blob On input, choose which blob to be fetched. > + On output, carry the full blob info. > + > + @retval EFI_NOT_FOUND Kernel is not fetched or no chosen node found in DT. > + @retval EFI_SUCCESS If there is kernel fetched or the Block->Name is not kernel. > + > +**/ > +STATIC > +EFI_STATUS > +FetchBlob ( > + IN OUT KERNEL_BLOB *Blob > + ) > +{ > + VOID *DeviceTreeBase; > + UINT64 InitrdStart, InitrdEnd; > + INT32 Len; > + CONST UINT64 *Prop; > + INT32 ChosenNode; > + > + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); > + ASSERT (DeviceTreeBase != NULL); > + > + Blob->Size = 0; > + > + // > + // Make sure we have a valid device tree blob > + // > + ASSERT (fdt_check_header (DeviceTreeBase) == 0); > + > + // > + // Find chosen node > + // > + ChosenNode = fdt_path_offset (DeviceTreeBase, "/chosen"); > + if (ChosenNode < 0) { > + return EFI_NOT_FOUND; > + } > + > + switch (Blob->Name[0]) { > + case 'k': > + Prop = fdt_getprop (DeviceTreeBase, ChosenNode, "linux,kernel-start", &Len); > + if ((Prop == NULL) || (Len < 0)) { > + return EFI_NOT_FOUND; > + } > + > + Blob->Data = (UINT8 *)fdt64_to_cpu (ReadUnaligned64 (Prop)); > + Prop = fdt_getprop (DeviceTreeBase, ChosenNode, "linux,kernel-size", &Len); > + if ((Prop == NULL) || (Len < 0)) { > + return EFI_SUCCESS; > + } > + > + Blob->Size = fdt64_to_cpu (ReadUnaligned64 (Prop)); > + break; > + case 'i': > + Prop = fdt_getprop (DeviceTreeBase, ChosenNode, "linux,initrd-start", &Len); > + if ((Prop == NULL) || (Len < 0)) { > + return EFI_SUCCESS; > + } > + > + InitrdStart = fdt64_to_cpu (ReadUnaligned64 (Prop)); > + Blob->Data = (UINT8 *)InitrdStart; > + Prop = fdt_getprop (DeviceTreeBase, ChosenNode, "linux,initrd-end", &Len); > + if ((Prop == NULL) || (Len < 0)) { > + return EFI_SUCCESS; > + } > + > + InitrdEnd = fdt64_to_cpu (ReadUnaligned64 (Prop)); > + Blob->Size = InitrdEnd - InitrdStart; > + break; > + case 'c': > + Prop = fdt_getprop (DeviceTreeBase, ChosenNode, "bootargs", &Len); > + if ((Prop == NULL) || (Len < 0)) { > + return EFI_SUCCESS; > + } > + > + Blob->Data = (UINT8 *)Prop; > + Blob->Size = Len; > + break; > + default: > + return EFI_SUCCESS; > + } > + > + return EFI_SUCCESS; > +} > + > +// > +// The entry point of the feature. > +// > + > +/** > + Download the kernel, the initial ramdisk, and the kernel command line from > + memory or DT. Construct a minimal SimpleFileSystem that contains the two > + image files. > + > + @param ImageHandle Image handle. > + @param SystemTable EFI system table. > + > + @return Error codes from any of the underlying > + functions. On success, the function doesn't > + return. > +**/ > +EFI_STATUS > +EFIAPI > +CloudHvKernelLoaderFsDxeEntrypoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + UINTN BlobType; > + KERNEL_BLOB *CurrentBlob; > + KERNEL_BLOB *KernelBlob; > + EFI_STATUS Status; > + EFI_HANDLE FileSystemHandle; > + EFI_HANDLE InitrdLoadFile2Handle; > + > + Status = gRT->GetTime (&mInitTime, NULL /* Capabilities */); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: GetTime(): %r\n", __FUNCTION__, Status)); > + return Status; > + } > + > + // > + // Fetch all blobs. > + // > + for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { > + CurrentBlob = &mKernelBlob[BlobType]; > + Status = FetchBlob (CurrentBlob); > + if (EFI_ERROR (Status)) { > + goto FreeBlobs; > + } > + > + Status = VerifyBlob ( > + CurrentBlob->Name, > + CurrentBlob->Data, > + CurrentBlob->Size > + ); > + if (EFI_ERROR (Status)) { > + goto FreeBlobs; > + } > + > + mTotalBlobBytes += CurrentBlob->Size; > + } > + > + KernelBlob = &mKernelBlob[KernelBlobTypeKernel]; > + > + if (KernelBlob->Data == NULL) { > + Status = EFI_NOT_FOUND; > + goto FreeBlobs; > + } > + > + // > + // Create a new handle with a single VenMedia() node device path protocol on > + // it, plus a custom SimpleFileSystem protocol on it. > + // > + FileSystemHandle = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &FileSystemHandle, > + &gEfiDevicePathProtocolGuid, > + &mFileSystemDevicePath, > + &gEfiSimpleFileSystemProtocolGuid, > + &mFileSystem, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: InstallMultipleProtocolInterfaces(): %r\n", > + __FUNCTION__, > + Status > + )); > + goto FreeBlobs; > + } > + > + if (KernelBlob[KernelBlobTypeInitrd].Size > 0) { > + InitrdLoadFile2Handle = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &InitrdLoadFile2Handle, > + &gEfiDevicePathProtocolGuid, > + &mInitrdDevicePath, > + &gEfiLoadFile2ProtocolGuid, > + &mInitrdLoadFile2, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "%a: InstallMultipleProtocolInterfaces(): %r\n", > + __FUNCTION__, > + Status > + )); > + goto UninstallFileSystemHandle; > + } > + } > + > + return EFI_SUCCESS; > + > +UninstallFileSystemHandle: > + Status = gBS->UninstallMultipleProtocolInterfaces ( > + FileSystemHandle, > + &gEfiDevicePathProtocolGuid, > + &mFileSystemDevicePath, > + &gEfiSimpleFileSystemProtocolGuid, > + &mFileSystem, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + > +FreeBlobs: > + while (BlobType > 0) { > + CurrentBlob = &mKernelBlob[--BlobType]; > + if (CurrentBlob->Data != NULL) { > + FreePool (CurrentBlob->Data); > + CurrentBlob->Size = 0; > + CurrentBlob->Data = NULL; > + } > + } > + > + return Status; > +} > diff --git a/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.inf b/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.inf > new file mode 100644 > index 0000000000..b7aa6ebb4e > --- /dev/null > +++ b/ArmVirtPkg/CloudHvKernelLoaderFsDxe/CloudHvKernelLoaderFsDxe.inf > @@ -0,0 +1,56 @@ > +## @file > +# DXE driver to expose the 'kernel', 'initrd' and 'cmdline' blobs > +# provided by Cloud Hypervisor as files in an abstract file system > +# > +# Copyright (C) 2022, Arm, Limited. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = CloudHvKernelLoaderFsDxe > + FILE_GUID = 57cdf541-2a29-4ae4-97e5-76a4aa2fe090 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = CloudHvKernelLoaderFsDxeEntrypoint > + > +[Sources] > + CloudHvKernelLoaderFsDxe.c > + > +[Packages] > + ArmVirtPkg/ArmVirtPkg.dec > + MdeModulePkg/MdeModulePkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + DevicePathLib > + FdtLib > + MemoryAllocationLib > + PcdLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiRuntimeServicesTableLib > + > +[Guids] > + gEfiFileInfoGuid > + gEfiFileSystemInfoGuid > + gEfiFileSystemVolumeLabelInfoIdGuid > + gQemuKernelLoaderFsMediaGuid > + > +[Protocols] > + gEfiDevicePathProtocolGuid ## PRODUCES > + gEfiLoadFile2ProtocolGuid ## PRODUCES > + gEfiSimpleFileSystemProtocolGuid ## PRODUCES > + > +[Depex] > + gEfiRealTimeClockArchProtocolGuid > + > +[FixedPcd] > + gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress