TianoCore EDK2 master
Loading...
Searching...
No Matches
LinuxInitrdDynamicShellCommand.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
12#include <Library/DebugLib.h>
14#include <Library/HiiLib.h>
16#include <Library/ShellLib.h>
19
21
22#include <Protocol/DevicePath.h>
24#include <Protocol/LoadFile2.h>
26
27#pragma pack (1)
28typedef struct {
29 VENDOR_DEVICE_PATH VenMediaNode;
32#pragma pack ()
33
34STATIC EFI_HII_HANDLE mLinuxInitrdShellCommandHiiHandle;
35STATIC EFI_PHYSICAL_ADDRESS mInitrdFileAddress;
36STATIC UINTN mInitrdFileSize;
37STATIC EFI_HANDLE mInitrdLoadFile2Handle;
38
39STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
40 { L"-u", TypeFlag },
41 { NULL, TypeMax }
42};
43
45 {
46 {
47 MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,{ sizeof (VENDOR_DEVICE_PATH) }
48 },
49 LINUX_EFI_INITRD_MEDIA_GUID
50 },{
51 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
52 { sizeof (EFI_DEVICE_PATH_PROTOCOL) }
53 }
54};
55
57BOOLEAN
58IsOtherInitrdDevicePathAlreadyInstalled (
59 VOID
60 )
61{
62 EFI_STATUS Status;
63 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
64 EFI_HANDLE Handle;
65
66 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mInitrdDevicePath;
67 Status = gBS->LocateDevicePath (
68 &gEfiLoadFile2ProtocolGuid,
69 &DevicePath,
70 &Handle
71 );
72 if (EFI_ERROR (Status)) {
73 return FALSE;
74 }
75
76 //
77 // Check whether the existing instance is one that we installed during
78 // a previous invocation.
79 //
80 if (Handle == mInitrdLoadFile2Handle) {
81 return FALSE;
82 }
83
84 return TRUE;
85}
86
89EFIAPI
90InitrdLoadFile2 (
93 IN BOOLEAN BootPolicy,
94 IN OUT UINTN *BufferSize,
95 OUT VOID *Buffer OPTIONAL
96 )
97{
98 if (BootPolicy) {
99 return EFI_UNSUPPORTED;
100 }
101
102 if ((BufferSize == NULL) || !IsDevicePathValid (FilePath, 0)) {
103 return EFI_INVALID_PARAMETER;
104 }
105
106 if ((FilePath->Type != END_DEVICE_PATH_TYPE) ||
107 (FilePath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE) ||
108 (mInitrdFileSize == 0))
109 {
110 return EFI_NOT_FOUND;
111 }
112
113 if ((Buffer == NULL) || (*BufferSize < mInitrdFileSize)) {
114 *BufferSize = mInitrdFileSize;
115 return EFI_BUFFER_TOO_SMALL;
116 }
117
118 ASSERT (mInitrdFileAddress != 0);
119
120 gBS->CopyMem (Buffer, (VOID *)(UINTN)mInitrdFileAddress, mInitrdFileSize);
121 *BufferSize = mInitrdFileSize;
122 return EFI_SUCCESS;
123}
124
125STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
126 InitrdLoadFile2,
127};
128
129STATIC
131UninstallLoadFile2Protocol (
132 VOID
133 )
134{
135 EFI_STATUS Status;
136
137 if (mInitrdLoadFile2Handle != NULL) {
138 Status = gBS->UninstallMultipleProtocolInterfaces (
139 mInitrdLoadFile2Handle,
140 &gEfiDevicePathProtocolGuid,
141 &mInitrdDevicePath,
142 &gEfiLoadFile2ProtocolGuid,
143 &mInitrdLoadFile2,
144 NULL
145 );
146 if (!EFI_ERROR (Status)) {
147 mInitrdLoadFile2Handle = NULL;
148 }
149
150 return Status;
151 }
152
153 return EFI_SUCCESS;
154}
155
156STATIC
157VOID
158FreeInitrdFile (
159 VOID
160 )
161{
162 if (mInitrdFileSize != 0) {
163 gBS->FreePages (mInitrdFileAddress, EFI_SIZE_TO_PAGES (mInitrdFileSize));
164 mInitrdFileSize = 0;
165 }
166}
167
168STATIC
170CacheInitrdFile (
171 IN SHELL_FILE_HANDLE FileHandle
172 )
173{
174 EFI_STATUS Status;
175 UINT64 FileSize;
176 UINTN ReadSize;
177
178 Status = gEfiShellProtocol->GetFileSize (FileHandle, &FileSize);
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182
183 if ((FileSize == 0) || (FileSize > MAX_UINTN)) {
184 return EFI_UNSUPPORTED;
185 }
186
187 Status = gBS->AllocatePages (
190 EFI_SIZE_TO_PAGES ((UINTN)FileSize),
191 &mInitrdFileAddress
192 );
193 if (EFI_ERROR (Status)) {
194 return Status;
195 }
196
197 ReadSize = (UINTN)FileSize;
198 Status = gEfiShellProtocol->ReadFile (
199 FileHandle,
200 &ReadSize,
201 (VOID *)(UINTN)mInitrdFileAddress
202 );
203 if (EFI_ERROR (Status) || (ReadSize < FileSize)) {
204 DEBUG ((
205 DEBUG_WARN,
206 "%a: failed to read initrd file - %r 0x%lx 0x%lx\n",
207 __func__,
208 Status,
209 (UINT64)ReadSize,
210 FileSize
211 ));
212 goto FreeMemory;
213 }
214
215 if (mInitrdLoadFile2Handle == NULL) {
216 Status = gBS->InstallMultipleProtocolInterfaces (
217 &mInitrdLoadFile2Handle,
218 &gEfiDevicePathProtocolGuid,
219 &mInitrdDevicePath,
220 &gEfiLoadFile2ProtocolGuid,
221 &mInitrdLoadFile2,
222 NULL
223 );
224 ASSERT_EFI_ERROR (Status);
225 }
226
227 mInitrdFileSize = (UINTN)FileSize;
228 return EFI_SUCCESS;
229
231 gBS->FreePages (mInitrdFileAddress, EFI_SIZE_TO_PAGES ((UINTN)FileSize));
232 return Status;
233}
234
241STATIC
243EFIAPI
245 IN EFI_HANDLE ImageHandle,
246 IN EFI_SYSTEM_TABLE *SystemTable
247 )
248{
249 EFI_STATUS Status;
250 LIST_ENTRY *Package;
251 CHAR16 *ProblemParam;
252 CONST CHAR16 *Param;
253 CHAR16 *Filename;
254 SHELL_STATUS ShellStatus;
255 SHELL_FILE_HANDLE FileHandle;
256
257 ProblemParam = NULL;
258 ShellStatus = SHELL_SUCCESS;
259
260 Status = ShellInitialize ();
261 ASSERT_EFI_ERROR (Status);
262
263 //
264 // parse the command line
265 //
266 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
267 if (EFI_ERROR (Status)) {
268 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
270 -1,
271 -1,
272 NULL,
273 STRING_TOKEN (STR_GEN_PROBLEM),
274 mLinuxInitrdShellCommandHiiHandle,
275 L"initrd",
276 ProblemParam
277 );
278 FreePool (ProblemParam);
279 ShellStatus = SHELL_INVALID_PARAMETER;
280 } else {
281 ASSERT (FALSE);
282 }
283 } else if (IsOtherInitrdDevicePathAlreadyInstalled ()) {
285 -1,
286 -1,
287 NULL,
288 STRING_TOKEN (STR_GEN_ALREADY_INSTALLED),
289 mLinuxInitrdShellCommandHiiHandle,
290 L"initrd"
291 );
292 ShellStatus = SHELL_UNSUPPORTED;
293 } else {
294 if (ShellCommandLineGetCount (Package) > 2) {
296 -1,
297 -1,
298 NULL,
299 STRING_TOKEN (STR_GEN_TOO_MANY),
300 mLinuxInitrdShellCommandHiiHandle,
301 L"initrd"
302 );
303 ShellStatus = SHELL_INVALID_PARAMETER;
304 } else if (ShellCommandLineGetCount (Package) < 2) {
305 if (ShellCommandLineGetFlag (Package, L"-u")) {
306 FreeInitrdFile ();
307 UninstallLoadFile2Protocol ();
308 } else {
310 -1,
311 -1,
312 NULL,
313 STRING_TOKEN (STR_GEN_TOO_FEW),
314 mLinuxInitrdShellCommandHiiHandle,
315 L"initrd"
316 );
317 ShellStatus = SHELL_INVALID_PARAMETER;
318 }
319 } else {
320 Param = ShellCommandLineGetRawValue (Package, 1);
321 ASSERT (Param != NULL);
322
323 Filename = ShellFindFilePath (Param);
324 if (Filename == NULL) {
326 -1,
327 -1,
328 NULL,
329 STRING_TOKEN (STR_GEN_FIND_FAIL),
330 mLinuxInitrdShellCommandHiiHandle,
331 L"initrd",
332 Param
333 );
334 ShellStatus = SHELL_NOT_FOUND;
335 } else {
336 Status = ShellOpenFileByName (
337 Filename,
338 &FileHandle,
339 EFI_FILE_MODE_READ,
340 0
341 );
342 if (!EFI_ERROR (Status)) {
343 FreeInitrdFile ();
344 Status = CacheInitrdFile (FileHandle);
345 ShellCloseFile (&FileHandle);
346 }
347
348 if (EFI_ERROR (Status)) {
350 -1,
351 -1,
352 NULL,
353 STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
354 mLinuxInitrdShellCommandHiiHandle,
355 L"initrd",
356 Param
357 );
358 ShellStatus = SHELL_NOT_FOUND;
359 }
360
361 FreePool (Filename);
362 }
363 }
364 }
365
366 return ShellStatus;
367}
368
384EFIAPI
387 IN EFI_SYSTEM_TABLE *SystemTable,
388 IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
390 )
391{
392 gEfiShellParametersProtocol = ShellParameters;
393 gEfiShellProtocol = Shell;
394
395 return RunInitrd (gImageHandle, SystemTable);
396}
397
410STATIC
411CHAR16 *
412EFIAPI
415 IN CONST CHAR8 *Language
416 )
417{
418 return HiiGetString (
419 mLinuxInitrdShellCommandHiiHandle,
420 STRING_TOKEN (STR_GET_HELP_INITRD),
421 Language
422 );
423}
424
425STATIC EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mLinuxInitrdDynamicCommand = {
426 L"initrd",
429};
430
438STATIC
441 EFI_HANDLE ImageHandle
442 )
443{
444 EFI_STATUS Status;
445 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
446 EFI_HII_HANDLE HiiHandle;
447
448 //
449 // Retrieve HII package list from ImageHandle
450 //
451 Status = gBS->OpenProtocol (
452 ImageHandle,
453 &gEfiHiiPackageListProtocolGuid,
454 (VOID **)&PackageList,
455 ImageHandle,
456 NULL,
457 EFI_OPEN_PROTOCOL_GET_PROTOCOL
458 );
459 ASSERT_EFI_ERROR (Status);
460 if (EFI_ERROR (Status)) {
461 return NULL;
462 }
463
464 //
465 // Publish HII package list to HII Database.
466 //
467 Status = gHiiDatabase->NewPackageList (
469 PackageList,
470 NULL,
471 &HiiHandle
472 );
473 ASSERT_EFI_ERROR (Status);
474 if (EFI_ERROR (Status)) {
475 return NULL;
476 }
477
478 return HiiHandle;
479}
480
494EFIAPI
496 IN EFI_HANDLE ImageHandle,
497 IN EFI_SYSTEM_TABLE *SystemTable
498 )
499{
500 EFI_STATUS Status;
501
502 mLinuxInitrdShellCommandHiiHandle = InitializeHiiPackage (ImageHandle);
503 if (mLinuxInitrdShellCommandHiiHandle == NULL) {
504 return EFI_ABORTED;
505 }
506
507 Status = gBS->InstallProtocolInterface (
508 &ImageHandle,
509 &gEfiShellDynamicCommandProtocolGuid,
511 &mLinuxInitrdDynamicCommand
512 );
513 ASSERT_EFI_ERROR (Status);
514 return Status;
515}
516
526EFIAPI
528 IN EFI_HANDLE ImageHandle
529 )
530{
531 EFI_STATUS Status;
532
533 FreeInitrdFile ();
534
535 Status = UninstallLoadFile2Protocol ();
536 if (EFI_ERROR (Status)) {
537 return Status;
538 }
539
540 Status = gBS->UninstallProtocolInterface (
541 ImageHandle,
542 &gEfiShellDynamicCommandProtocolGuid,
543 &mLinuxInitrdDynamicCommand
544 );
545 if (EFI_ERROR (Status)) {
546 return Status;
547 }
548
549 HiiRemovePackages (mLinuxInitrdShellCommandHiiHandle);
550 return EFI_SUCCESS;
551}
UINT64 UINTN
VOID FreeMemory(VOID)
Definition: Compress.c:216
#define MEDIA_VENDOR_DP
Media vendor device path subtype.
Definition: DevicePath.h:1093
BOOLEAN EFIAPI IsDevicePathValid(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STRING EFIAPI HiiGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId, IN CONST CHAR8 *Language OPTIONAL)
Definition: HiiString.c:211
VOID EFIAPI HiiRemovePackages(IN EFI_HII_HANDLE HiiHandle)
Definition: HiiLib.c:253
EFI_STATUS EFIAPI LinuxInitrdDynamicShellCommandUnload(IN EFI_HANDLE ImageHandle)
STATIC EFI_HII_HANDLE InitializeHiiPackage(EFI_HANDLE ImageHandle)
EFI_STATUS EFIAPI LinuxInitrdDynamicShellCommandEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
SHELL_STATUS EFIAPI LinuxInitrdCommandHandler(IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, IN EFI_SYSTEM_TABLE *SystemTable, IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN EFI_SHELL_PROTOCOL *Shell)
STATIC SHELL_STATUS EFIAPI RunInitrd(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC CHAR16 *EFIAPI LinuxInitrdGetHelp(IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, IN CONST CHAR8 *Language)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_SUCCESS
Definition: Shell.h:25
@ SHELL_NOT_FOUND
Definition: Shell.h:101
@ SHELL_UNSUPPORTED
Definition: Shell.h:40
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
#define ShellCommandLineParse(CheckList, CheckPackage, ProblemParam, AutoPageBreak)
Make it easy to upgrade from older versions of the shell library.
Definition: ShellLib.h:755
EFI_STATUS EFIAPI ShellPrintHiiEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR8 *Language OPTIONAL, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle,...)
BOOLEAN EFIAPI ShellCommandLineGetFlag(IN CONST LIST_ENTRY *CONST CheckPackage, IN CONST CHAR16 *CONST KeyString)
@ TypeFlag
A flag that is present or not present only (IE "-a").
Definition: ShellLib.h:699
EFI_STATUS EFIAPI ShellOpenFileByName(IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: UefiShellLib.c:720
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
CHAR16 *EFIAPI ShellFindFilePath(IN CONST CHAR16 *FileName)
CONST CHAR16 *EFIAPI ShellCommandLineGetRawValue(IN CONST LIST_ENTRY *CONST CheckPackage, IN UINTN Position)
UINTN EFIAPI ShellCommandLineGetCount(IN CONST LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellCloseFile(IN SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:969
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_HII_DATABASE_PROTOCOL * gHiiDatabase
#define STRING_TOKEN(t)
VOID * EFI_HII_HANDLE
@ EfiLoaderData
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
@ AllocateAnyPages
Definition: UefiSpec.h:33
EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL protocol structure.