2 HII Config Access protocol implementation of RamDiskDxe driver.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016-2018 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "RamDiskImpl.h"
12 CHAR16 mRamDiskStorageName
[] = L
"RAM_DISK_CONFIGURATION";
14 RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate
= {
15 RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE
,
18 RAM_DISK_BOOT_SERVICE_DATA_MEMORY
27 HII_VENDOR_DEVICE_PATH mRamDiskHiiVendorDevicePath
= {
33 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
34 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
37 RAM_DISK_FORM_SET_GUID
41 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 (UINT8
) (END_DEVICE_PATH_LENGTH
),
44 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 This function publish the RAM disk configuration Form.
53 @param[in, out] ConfigPrivateData
54 Points to RAM disk configuration private data.
56 @retval EFI_SUCCESS HII Form is installed successfully.
57 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
58 @retval Others Other errors as indicated.
62 InstallRamDiskConfigForm (
63 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
67 EFI_HII_HANDLE HiiHandle
;
68 EFI_HANDLE DriverHandle
;
69 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
72 ConfigAccess
= &ConfigPrivateData
->ConfigAccess
;
73 Status
= gBS
->InstallMultipleProtocolInterfaces (
75 &gEfiDevicePathProtocolGuid
,
76 &mRamDiskHiiVendorDevicePath
,
77 &gEfiHiiConfigAccessProtocolGuid
,
81 if (EFI_ERROR (Status
)) {
85 ConfigPrivateData
->DriverHandle
= DriverHandle
;
88 // Publish the HII package list
90 HiiHandle
= HiiAddPackages (
97 if (HiiHandle
== NULL
) {
98 gBS
->UninstallMultipleProtocolInterfaces (
100 &gEfiDevicePathProtocolGuid
,
101 &mRamDiskHiiVendorDevicePath
,
102 &gEfiHiiConfigAccessProtocolGuid
,
106 return EFI_OUT_OF_RESOURCES
;
109 ConfigPrivateData
->HiiHandle
= HiiHandle
;
116 This function removes RAM disk configuration Form.
118 @param[in, out] ConfigPrivateData
119 Points to RAM disk configuration private data.
123 UninstallRamDiskConfigForm (
124 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
128 // Uninstall HII package list
130 if (ConfigPrivateData
->HiiHandle
!= NULL
) {
131 HiiRemovePackages (ConfigPrivateData
->HiiHandle
);
132 ConfigPrivateData
->HiiHandle
= NULL
;
136 // Uninstall HII Config Access Protocol
138 if (ConfigPrivateData
->DriverHandle
!= NULL
) {
139 gBS
->UninstallMultipleProtocolInterfaces (
140 ConfigPrivateData
->DriverHandle
,
141 &gEfiDevicePathProtocolGuid
,
142 &mRamDiskHiiVendorDevicePath
,
143 &gEfiHiiConfigAccessProtocolGuid
,
144 &ConfigPrivateData
->ConfigAccess
,
147 ConfigPrivateData
->DriverHandle
= NULL
;
150 FreePool (ConfigPrivateData
);
155 Unregister all registered RAM disks.
159 UnregisterAllRamDisks (
164 LIST_ENTRY
*NextEntry
;
165 RAM_DISK_PRIVATE_DATA
*PrivateData
;
167 if (!IsListEmpty(&RegisteredRamDisks
)) {
168 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
169 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
171 gBS
->UninstallMultipleProtocolInterfaces (
173 &gEfiBlockIoProtocolGuid
,
174 &PrivateData
->BlockIo
,
175 &gEfiBlockIo2ProtocolGuid
,
176 &PrivateData
->BlockIo2
,
177 &gEfiDevicePathProtocolGuid
,
178 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
182 RemoveEntryList (&PrivateData
->ThisInstance
);
184 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
186 // If a RAM disk is created within HII, then the RamDiskDxe driver
187 // driver is responsible for freeing the allocated memory for the
190 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
193 FreePool (PrivateData
->DevicePath
);
194 FreePool (PrivateData
);
201 This function allows a caller to extract the current configuration for one
202 or more named elements from the target driver.
204 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
205 @param[in] Request A null-terminated Unicode string in
206 <ConfigRequest> format.
207 @param[out] Progress On return, points to a character in the Request
208 string. Points to the string's null terminator if
209 request was successful. Points to the most recent
210 '&' before the first failing name/value pair (or
211 the beginning of the string if the failure is in
212 the first name/value pair) if the request was not
214 @param[out] Results A null-terminated Unicode string in
215 <ConfigAltResp> format which has all values filled
216 in for the names in the Request string. String to
217 be allocated by the called function.
219 @retval EFI_SUCCESS The Results is filled with the requested
221 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
222 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
223 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
229 RamDiskExtractConfig (
230 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
231 IN CONST EFI_STRING Request
,
232 OUT EFI_STRING
*Progress
,
233 OUT EFI_STRING
*Results
236 if (Progress
== NULL
|| Results
== NULL
) {
237 return EFI_INVALID_PARAMETER
;
240 return EFI_NOT_FOUND
;
245 This function processes the results of changes in configuration.
247 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
248 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
250 @param[out] Progress A pointer to a string filled in with the offset of
251 the most recent '&' before the first failing
252 name/value pair (or the beginning of the string if
253 the failure is in the first name/value pair) or
254 the terminating NULL if all was successful.
256 @retval EFI_SUCCESS The Results is processed successfully.
257 @retval EFI_INVALID_PARAMETER Configuration is NULL.
258 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
265 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
266 IN CONST EFI_STRING Configuration
,
267 OUT EFI_STRING
*Progress
270 if (Configuration
== NULL
|| Progress
== NULL
) {
271 return EFI_INVALID_PARAMETER
;
274 *Progress
= Configuration
;
276 return EFI_NOT_FOUND
;
281 Allocate memory and register the RAM disk created within RamDiskDxe
284 @param[in] Size If creating raw, size of the RAM disk to create.
285 If creating from file, zero.
286 @param[in] FileHandle If creating raw, NULL. If creating from file, the
288 @param[in] MemoryType Type of memory to be used to create RAM Disk.
290 @retval EFI_SUCCESS RAM disk is created and registered.
291 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the
298 IN EFI_FILE_HANDLE FileHandle
,
304 UINT64
*StartingAddr
;
306 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
307 RAM_DISK_PRIVATE_DATA
*PrivateData
;
308 EFI_FILE_INFO
*FileInformation
;
310 FileInformation
= NULL
;
313 if (FileHandle
!= NULL
) {
317 FileInformation
= FileInfo (FileHandle
);
318 if (NULL
== FileInformation
) {
321 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
324 L
"Not enough memory to get the file information!",
325 L
"Press ENTER to continue ...",
329 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
331 return EFI_OUT_OF_RESOURCES
;
335 // Update the size of RAM disk according to the file size.
337 Size
= FileInformation
->FileSize
;
340 if (Size
> (UINTN
) -1) {
343 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
346 L
"The given RAM disk size is too large!",
347 L
"Press ENTER to continue ...",
351 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
353 return EFI_OUT_OF_RESOURCES
;
356 if (MemoryType
== RAM_DISK_BOOT_SERVICE_DATA_MEMORY
) {
357 Status
= gBS
->AllocatePool (
360 (VOID
**)&StartingAddr
362 } else if (MemoryType
== RAM_DISK_RESERVED_MEMORY
) {
363 Status
= gBS
->AllocatePool (
364 EfiReservedMemoryType
,
366 (VOID
**)&StartingAddr
369 Status
= EFI_INVALID_PARAMETER
;
372 if ((StartingAddr
== NULL
) || EFI_ERROR(Status
)) {
375 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
378 L
"Not enough memory to create the RAM disk!",
379 L
"Press ENTER to continue ...",
383 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
385 return EFI_OUT_OF_RESOURCES
;
388 if (FileHandle
!= NULL
) {
390 // Copy the file content to the RAM disk.
392 BufferSize
= (UINTN
) Size
;
396 (VOID
*)(UINTN
) StartingAddr
398 if (BufferSize
!= FileInformation
->FileSize
) {
401 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
404 L
"File content read error!",
405 L
"Press ENTER to continue ...",
409 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
411 return EFI_DEVICE_ERROR
;
416 // Register the newly created RAM disk.
418 Status
= RamDiskRegister (
419 ((UINT64
)(UINTN
) StartingAddr
),
421 &gEfiVirtualDiskGuid
,
425 if (EFI_ERROR (Status
)) {
428 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
431 L
"Fail to register the newly created RAM disk!",
432 L
"Press ENTER to continue ...",
436 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
442 // If RAM disk is created within HII, memory should be freed when the
443 // RAM disk is unregisterd.
445 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks
.BackLink
);
446 PrivateData
->CreateMethod
= RamDiskCreateHii
;
453 This function updates the registered RAM disks list on the main form.
455 @param[in, out] ConfigPrivate
456 Private data for configurating hii data for RAM
462 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
465 VOID
*StartOpCodeHandle
;
466 VOID
*EndOpCodeHandle
;
467 EFI_IFR_GUID_LABEL
*StartLabel
;
468 EFI_IFR_GUID_LABEL
*EndLabel
;
471 RAM_DISK_PRIVATE_DATA
*PrivateData
;
473 CHAR16 RamDiskStr
[128];
474 EFI_STRING_ID StringId
;
477 // Init OpCode Handle
479 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
480 ASSERT (StartOpCodeHandle
!= NULL
);
482 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
483 ASSERT (EndOpCodeHandle
!= NULL
);
486 // Create Hii Extend Label OpCode as the start opcode
488 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
492 sizeof (EFI_IFR_GUID_LABEL
)
494 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
495 StartLabel
->Number
= MAIN_LABEL_LIST_START
;
498 // Create Hii Extend Label OpCode as the end opcode
500 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
504 sizeof (EFI_IFR_GUID_LABEL
)
506 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
507 EndLabel
->Number
= MAIN_LABEL_LIST_END
;
510 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
511 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
512 PrivateData
->CheckBoxId
= (EFI_QUESTION_ID
)
513 (MAIN_CHECKBOX_QUESTION_ID_START
+ Index
);
515 // CheckBox is unchecked by default.
517 PrivateData
->CheckBoxChecked
= FALSE
;
523 L
" RAM Disk %d: [0x%lx, 0x%lx]\n",
525 PrivateData
->StartingAddr
,
526 PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
529 StringId
= HiiSetString (ConfigPrivate
->HiiHandle
, 0, RamDiskStr
, NULL
);
530 ASSERT (StringId
!= 0);
532 HiiCreateCheckBoxOpCode (
534 PrivateData
->CheckBoxId
,
538 STRING_TOKEN (STR_RAM_DISK_LIST_HELP
),
539 EFI_IFR_FLAG_CALLBACK
,
548 ConfigPrivate
->HiiHandle
,
549 &gRamDiskFormSetGuid
,
555 HiiFreeOpCodeHandle (StartOpCodeHandle
);
556 HiiFreeOpCodeHandle (EndOpCodeHandle
);
561 This function processes the results of changes in configuration.
563 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
564 @param[in] Action Specifies the type of action taken by the browser.
565 @param[in] QuestionId A unique value which is sent to the original
566 exporting driver so that it can identify the type
568 @param[in] Type The type of value for the question.
569 @param[in] Value A pointer to the data being sent to the original
571 @param[out] ActionRequest On return, points to the action requested by the
574 @retval EFI_SUCCESS The callback successfully handled the action.
575 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
576 variable and its data.
577 @retval EFI_DEVICE_ERROR The variable could not be saved.
578 @retval EFI_UNSUPPORTED The specified Action is not supported by the
585 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
586 IN EFI_BROWSER_ACTION Action
,
587 IN EFI_QUESTION_ID QuestionId
,
589 IN EFI_IFR_TYPE_VALUE
*Value
,
590 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
594 RAM_DISK_PRIVATE_DATA
*PrivateData
;
595 RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
;
596 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
597 EFI_FILE_HANDLE FileHandle
;
599 LIST_ENTRY
*NextEntry
;
601 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
602 return EFI_INVALID_PARAMETER
;
605 ConfigPrivate
= RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This
);
607 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
608 Status
= EFI_UNSUPPORTED
;
609 if (QuestionId
== CREATE_RAW_SIZE_QUESTION_ID
) {
610 Value
->u64
= EFI_PAGE_SIZE
;
611 ConfigPrivate
->ConfigStore
.Size
= EFI_PAGE_SIZE
;
612 Status
= EFI_SUCCESS
;
613 } else if (QuestionId
== CREATE_RAW_MEMORY_TYPE_QUESTION_ID
) {
614 Value
->u8
= RAM_DISK_BOOT_SERVICE_DATA_MEMORY
;
615 ConfigPrivate
->ConfigStore
.MemType
= RAM_DISK_BOOT_SERVICE_DATA_MEMORY
;
616 Status
= EFI_SUCCESS
;
621 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
622 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
623 (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
)) {
624 return EFI_UNSUPPORTED
;
628 // Update the RAM disk list show at the main form first.
630 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
631 Status
= EFI_UNSUPPORTED
;
632 if (QuestionId
== MAIN_GOTO_FILE_EXPLORER_ID
) {
633 UpdateMainForm (ConfigPrivate
);
634 Status
= EFI_SUCCESS
;
639 Status
= EFI_SUCCESS
;
641 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
642 switch (QuestionId
) {
643 case MAIN_GOTO_FILE_EXPLORER_ID
:
644 Status
= ChooseFile (NULL
, NULL
, NULL
, &FileDevPath
);
645 if (EFI_ERROR (Status
)) {
649 if (FileDevPath
!= NULL
) {
653 Status
= EfiOpenFileByDevicePath (
659 if (EFI_ERROR (Status
)) {
664 // Create from file, RAM disk size is zero. It will be updated
665 // according to the file size.
667 Status
= HiiCreateRamDisk (
670 ConfigPrivate
->ConfigStore
.MemType
672 if (EFI_ERROR (Status
)) {
677 // Refresh the registered RAM disks list.
679 UpdateMainForm (ConfigPrivate
);
686 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
687 switch (QuestionId
) {
688 case MAIN_REMOVE_RD_QUESTION_ID
:
690 // Remove the selected RAM disks
692 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
693 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
694 if (PrivateData
->CheckBoxChecked
) {
696 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
701 UpdateMainForm (ConfigPrivate
);
703 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
706 case CREATE_RAW_SIZE_QUESTION_ID
:
707 ConfigPrivate
->ConfigStore
.Size
= Value
->u64
;
710 case CREATE_RAW_MEMORY_TYPE_QUESTION_ID
:
711 ConfigPrivate
->ConfigStore
.MemType
= Value
->u8
;
714 case CREATE_RAW_SUBMIT_QUESTION_ID
:
716 // Create raw, FileHandle is NULL.
718 Status
= HiiCreateRamDisk (
719 ConfigPrivate
->ConfigStore
.Size
,
721 ConfigPrivate
->ConfigStore
.MemType
723 if (EFI_ERROR (Status
)) {
728 // Refresh the registered RAM disks list.
730 UpdateMainForm (ConfigPrivate
);
732 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
735 case CREATE_RAW_DISCARD_QUESTION_ID
:
736 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
741 // QuestionIds for checkboxes
743 if ((QuestionId
>= MAIN_CHECKBOX_QUESTION_ID_START
) &&
744 (QuestionId
< CREATE_RAW_RAM_DISK_FORM_ID
)) {
745 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
746 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
747 if (PrivateData
->CheckBoxId
== QuestionId
) {
748 PrivateData
->CheckBoxChecked
= (BOOLEAN
) (Value
->u8
!= 0);