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 Copyright (c) Microsoft Corporation.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "RamDiskImpl.h"
13 CHAR16 mRamDiskStorageName
[] = L
"RAM_DISK_CONFIGURATION";
15 RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate
= {
16 RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE
,
19 RAM_DISK_BOOT_SERVICE_DATA_MEMORY
28 HII_VENDOR_DEVICE_PATH mRamDiskHiiVendorDevicePath
= {
34 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 RAM_DISK_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
)(END_DEVICE_PATH_LENGTH
),
45 (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
;
115 This function removes RAM disk configuration Form.
117 @param[in, out] ConfigPrivateData
118 Points to RAM disk configuration private data.
122 UninstallRamDiskConfigForm (
123 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
127 // Uninstall HII package list
129 if (ConfigPrivateData
->HiiHandle
!= NULL
) {
130 HiiRemovePackages (ConfigPrivateData
->HiiHandle
);
131 ConfigPrivateData
->HiiHandle
= NULL
;
135 // Uninstall HII Config Access Protocol
137 if (ConfigPrivateData
->DriverHandle
!= NULL
) {
138 gBS
->UninstallMultipleProtocolInterfaces (
139 ConfigPrivateData
->DriverHandle
,
140 &gEfiDevicePathProtocolGuid
,
141 &mRamDiskHiiVendorDevicePath
,
142 &gEfiHiiConfigAccessProtocolGuid
,
143 &ConfigPrivateData
->ConfigAccess
,
146 ConfigPrivateData
->DriverHandle
= NULL
;
149 FreePool (ConfigPrivateData
);
153 Unregister all registered RAM disks.
157 UnregisterAllRamDisks (
162 LIST_ENTRY
*NextEntry
;
163 RAM_DISK_PRIVATE_DATA
*PrivateData
;
165 if (!IsListEmpty (&RegisteredRamDisks
)) {
166 BASE_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
167 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
169 gBS
->UninstallMultipleProtocolInterfaces (
171 &gEfiBlockIoProtocolGuid
,
172 &PrivateData
->BlockIo
,
173 &gEfiBlockIo2ProtocolGuid
,
174 &PrivateData
->BlockIo2
,
175 &gEfiDevicePathProtocolGuid
,
176 (EFI_DEVICE_PATH_PROTOCOL
*)PrivateData
->DevicePath
,
180 RemoveEntryList (&PrivateData
->ThisInstance
);
182 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
184 // If a RAM disk is created within HII, then the RamDiskDxe driver
185 // driver is responsible for freeing the allocated memory for the
188 FreePool ((VOID
*)(UINTN
)PrivateData
->StartingAddr
);
191 FreePool (PrivateData
->DevicePath
);
192 FreePool (PrivateData
);
198 This function allows a caller to extract the current configuration for one
199 or more named elements from the target driver.
201 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
202 @param[in] Request A null-terminated Unicode string in
203 <ConfigRequest> format.
204 @param[out] Progress On return, points to a character in the Request
205 string. Points to the string's null terminator if
206 request was successful. Points to the most recent
207 '&' before the first failing name/value pair (or
208 the beginning of the string if the failure is in
209 the first name/value pair) if the request was not
211 @param[out] Results A null-terminated Unicode string in
212 <ConfigAltResp> format which has all values filled
213 in for the names in the Request string. String to
214 be allocated by the called function.
216 @retval EFI_SUCCESS The Results is filled with the requested
218 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
219 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
220 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
226 RamDiskExtractConfig (
227 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
228 IN CONST EFI_STRING Request
,
229 OUT EFI_STRING
*Progress
,
230 OUT EFI_STRING
*Results
233 if ((Progress
== NULL
) || (Results
== NULL
)) {
234 return EFI_INVALID_PARAMETER
;
238 return EFI_NOT_FOUND
;
242 This function processes the results of changes in configuration.
244 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
245 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
247 @param[out] Progress A pointer to a string filled in with the offset of
248 the most recent '&' before the first failing
249 name/value pair (or the beginning of the string if
250 the failure is in the first name/value pair) or
251 the terminating NULL if all was successful.
253 @retval EFI_SUCCESS The Results is processed successfully.
254 @retval EFI_INVALID_PARAMETER Configuration is NULL.
255 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
262 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
263 IN CONST EFI_STRING Configuration
,
264 OUT EFI_STRING
*Progress
267 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
268 return EFI_INVALID_PARAMETER
;
271 *Progress
= Configuration
;
273 return EFI_NOT_FOUND
;
277 Allocate memory and register the RAM disk created within RamDiskDxe
280 @param[in] Size If creating raw, size of the RAM disk to create.
281 If creating from file, zero.
282 @param[in] FileHandle If creating raw, NULL. If creating from file, the
284 @param[in] MemoryType Type of memory to be used to create RAM Disk.
286 @retval EFI_SUCCESS RAM disk is created and registered.
287 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the
294 IN EFI_FILE_HANDLE FileHandle
,
300 UINT64
*StartingAddr
;
302 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
303 RAM_DISK_PRIVATE_DATA
*PrivateData
;
304 EFI_FILE_INFO
*FileInformation
;
306 FileInformation
= NULL
;
309 if (FileHandle
!= NULL
) {
313 FileInformation
= FileInfo (FileHandle
);
314 if (NULL
== FileInformation
) {
317 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
320 L
"Not enough memory to get the file information!",
321 L
"Press ENTER to continue ...",
325 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
327 return EFI_OUT_OF_RESOURCES
;
331 // Update the size of RAM disk according to the file size.
333 Size
= FileInformation
->FileSize
;
336 if (Size
> (UINTN
)-1) {
339 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
342 L
"The given RAM disk size is too large!",
343 L
"Press ENTER to continue ...",
347 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
349 return EFI_OUT_OF_RESOURCES
;
352 if (MemoryType
== RAM_DISK_BOOT_SERVICE_DATA_MEMORY
) {
353 Status
= gBS
->AllocatePool (
356 (VOID
**)&StartingAddr
358 } else if (MemoryType
== RAM_DISK_RESERVED_MEMORY
) {
359 Status
= gBS
->AllocatePool (
360 EfiReservedMemoryType
,
362 (VOID
**)&StartingAddr
365 Status
= EFI_INVALID_PARAMETER
;
368 if ((StartingAddr
== NULL
) || EFI_ERROR (Status
)) {
371 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
374 L
"Not enough memory to create the RAM disk!",
375 L
"Press ENTER to continue ...",
379 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
381 return EFI_OUT_OF_RESOURCES
;
384 if (FileHandle
!= NULL
) {
386 // Copy the file content to the RAM disk.
388 BufferSize
= (UINTN
)Size
;
392 (VOID
*)(UINTN
)StartingAddr
394 if (BufferSize
!= FileInformation
->FileSize
) {
397 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
400 L
"File content read error!",
401 L
"Press ENTER to continue ...",
405 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
407 return EFI_DEVICE_ERROR
;
412 // Register the newly created RAM disk.
414 Status
= RamDiskRegister (
415 ((UINT64
)(UINTN
)StartingAddr
),
417 &gEfiVirtualDiskGuid
,
421 if (EFI_ERROR (Status
)) {
424 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
427 L
"Fail to register the newly created RAM disk!",
428 L
"Press ENTER to continue ...",
432 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
438 // If RAM disk is created within HII, memory should be freed when the
439 // RAM disk is unregisterd.
441 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks
.BackLink
);
442 PrivateData
->CreateMethod
= RamDiskCreateHii
;
448 This function updates the registered RAM disks list on the main form.
450 @param[in, out] ConfigPrivate
451 Private data for configurating hii data for RAM
457 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
460 VOID
*StartOpCodeHandle
;
461 VOID
*EndOpCodeHandle
;
462 EFI_IFR_GUID_LABEL
*StartLabel
;
463 EFI_IFR_GUID_LABEL
*EndLabel
;
466 RAM_DISK_PRIVATE_DATA
*PrivateData
;
468 CHAR16 RamDiskStr
[128];
469 EFI_STRING_ID StringId
;
472 // Init OpCode Handle
474 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
475 ASSERT (StartOpCodeHandle
!= NULL
);
477 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
478 ASSERT (EndOpCodeHandle
!= NULL
);
481 // Create Hii Extend Label OpCode as the start opcode
483 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
487 sizeof (EFI_IFR_GUID_LABEL
)
489 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
490 StartLabel
->Number
= MAIN_LABEL_LIST_START
;
493 // Create Hii Extend Label OpCode as the end opcode
495 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
499 sizeof (EFI_IFR_GUID_LABEL
)
501 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
502 EndLabel
->Number
= MAIN_LABEL_LIST_END
;
505 BASE_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
506 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
507 PrivateData
->CheckBoxId
= (EFI_QUESTION_ID
)
508 (MAIN_CHECKBOX_QUESTION_ID_START
+ Index
);
510 // CheckBox is unchecked by default.
512 PrivateData
->CheckBoxChecked
= FALSE
;
518 L
" RAM Disk %d: [0x%lx, 0x%lx]\n",
520 PrivateData
->StartingAddr
,
521 PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
524 StringId
= HiiSetString (ConfigPrivate
->HiiHandle
, 0, RamDiskStr
, NULL
);
525 ASSERT (StringId
!= 0);
527 HiiCreateCheckBoxOpCode (
529 PrivateData
->CheckBoxId
,
533 STRING_TOKEN (STR_RAM_DISK_LIST_HELP
),
534 EFI_IFR_FLAG_CALLBACK
,
543 ConfigPrivate
->HiiHandle
,
544 &gRamDiskFormSetGuid
,
550 HiiFreeOpCodeHandle (StartOpCodeHandle
);
551 HiiFreeOpCodeHandle (EndOpCodeHandle
);
555 This function processes the results of changes in configuration.
557 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
558 @param[in] Action Specifies the type of action taken by the browser.
559 @param[in] QuestionId A unique value which is sent to the original
560 exporting driver so that it can identify the type
562 @param[in] Type The type of value for the question.
563 @param[in] Value A pointer to the data being sent to the original
565 @param[out] ActionRequest On return, points to the action requested by the
568 @retval EFI_SUCCESS The callback successfully handled the action.
569 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
570 variable and its data.
571 @retval EFI_DEVICE_ERROR The variable could not be saved.
572 @retval EFI_UNSUPPORTED The specified Action is not supported by the
579 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
580 IN EFI_BROWSER_ACTION Action
,
581 IN EFI_QUESTION_ID QuestionId
,
583 IN EFI_IFR_TYPE_VALUE
*Value
,
584 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
588 RAM_DISK_PRIVATE_DATA
*PrivateData
;
589 RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
;
590 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
591 EFI_FILE_HANDLE FileHandle
;
593 LIST_ENTRY
*NextEntry
;
595 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
596 return EFI_INVALID_PARAMETER
;
599 ConfigPrivate
= RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This
);
601 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
602 Status
= EFI_UNSUPPORTED
;
603 if (QuestionId
== CREATE_RAW_SIZE_QUESTION_ID
) {
604 Value
->u64
= EFI_PAGE_SIZE
;
605 ConfigPrivate
->ConfigStore
.Size
= EFI_PAGE_SIZE
;
606 Status
= EFI_SUCCESS
;
607 } else if (QuestionId
== CREATE_RAW_MEMORY_TYPE_QUESTION_ID
) {
608 Value
->u8
= RAM_DISK_BOOT_SERVICE_DATA_MEMORY
;
609 ConfigPrivate
->ConfigStore
.MemType
= RAM_DISK_BOOT_SERVICE_DATA_MEMORY
;
610 Status
= EFI_SUCCESS
;
616 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
617 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
618 (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
))
620 return EFI_UNSUPPORTED
;
624 // Update the RAM disk list show at the main form first.
626 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
627 Status
= EFI_UNSUPPORTED
;
628 if (QuestionId
== MAIN_GOTO_FILE_EXPLORER_ID
) {
629 UpdateMainForm (ConfigPrivate
);
630 Status
= EFI_SUCCESS
;
636 Status
= EFI_SUCCESS
;
638 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
639 switch (QuestionId
) {
640 case MAIN_GOTO_FILE_EXPLORER_ID
:
641 Status
= ChooseFile (NULL
, NULL
, NULL
, &FileDevPath
);
642 if (EFI_ERROR (Status
)) {
646 if (FileDevPath
!= NULL
) {
650 Status
= EfiOpenFileByDevicePath (
656 if (EFI_ERROR (Status
)) {
661 // Create from file, RAM disk size is zero. It will be updated
662 // according to the file size.
664 Status
= HiiCreateRamDisk (
667 ConfigPrivate
->ConfigStore
.MemType
669 if (EFI_ERROR (Status
)) {
674 // Refresh the registered RAM disks list.
676 UpdateMainForm (ConfigPrivate
);
684 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
685 switch (QuestionId
) {
686 case MAIN_REMOVE_RD_QUESTION_ID
:
688 // Remove the selected RAM disks
690 BASE_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
691 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
692 if (PrivateData
->CheckBoxChecked
) {
694 (EFI_DEVICE_PATH_PROTOCOL
*)PrivateData
->DevicePath
699 UpdateMainForm (ConfigPrivate
);
701 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
704 case CREATE_RAW_SIZE_QUESTION_ID
:
705 ConfigPrivate
->ConfigStore
.Size
= Value
->u64
;
708 case CREATE_RAW_MEMORY_TYPE_QUESTION_ID
:
709 ConfigPrivate
->ConfigStore
.MemType
= Value
->u8
;
712 case CREATE_RAW_SUBMIT_QUESTION_ID
:
714 // Create raw, FileHandle is NULL.
716 Status
= HiiCreateRamDisk (
717 ConfigPrivate
->ConfigStore
.Size
,
719 ConfigPrivate
->ConfigStore
.MemType
721 if (EFI_ERROR (Status
)) {
726 // Refresh the registered RAM disks list.
728 UpdateMainForm (ConfigPrivate
);
730 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
733 case CREATE_RAW_DISCARD_QUESTION_ID
:
734 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
739 // QuestionIds for checkboxes
741 if ((QuestionId
>= MAIN_CHECKBOX_QUESTION_ID_START
) &&
742 (QuestionId
< CREATE_RAW_RAM_DISK_FORM_ID
))
744 BASE_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
745 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
746 if (PrivateData
->CheckBoxId
== QuestionId
) {
747 PrivateData
->CheckBoxChecked
= (BOOLEAN
)(Value
->u8
!= 0);