2 HII Config Access protocol implementation of RamDiskDxe driver.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "RamDiskImpl.h"
17 CHAR16 mRamDiskStorageName
[] = L
"RAM_DISK_CONFIGURATION";
19 RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate
= {
20 RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE
,
31 HII_VENDOR_DEVICE_PATH mRamDiskHiiVendorDevicePath
= {
37 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
38 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
41 RAM_DISK_FORM_SET_GUID
45 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
47 (UINT8
) (END_DEVICE_PATH_LENGTH
),
48 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
55 This function publish the RAM disk configuration Form.
57 @param[in, out] ConfigPrivateData
58 Points to RAM disk configuration private data.
60 @retval EFI_SUCCESS HII Form is installed successfully.
61 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
62 @retval Others Other errors as indicated.
66 InstallRamDiskConfigForm (
67 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
71 EFI_HII_HANDLE HiiHandle
;
72 EFI_HANDLE DriverHandle
;
73 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
76 ConfigAccess
= &ConfigPrivateData
->ConfigAccess
;
77 Status
= gBS
->InstallMultipleProtocolInterfaces (
79 &gEfiDevicePathProtocolGuid
,
80 &mRamDiskHiiVendorDevicePath
,
81 &gEfiHiiConfigAccessProtocolGuid
,
85 if (EFI_ERROR (Status
)) {
89 ConfigPrivateData
->DriverHandle
= DriverHandle
;
92 // Publish the HII package list
94 HiiHandle
= HiiAddPackages (
101 if (HiiHandle
== NULL
) {
102 gBS
->UninstallMultipleProtocolInterfaces (
104 &gEfiDevicePathProtocolGuid
,
105 &mRamDiskHiiVendorDevicePath
,
106 &gEfiHiiConfigAccessProtocolGuid
,
110 return EFI_OUT_OF_RESOURCES
;
113 ConfigPrivateData
->HiiHandle
= HiiHandle
;
120 This function removes RAM disk configuration Form.
122 @param[in, out] ConfigPrivateData
123 Points to RAM disk configuration private data.
127 UninstallRamDiskConfigForm (
128 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
132 // Uninstall HII package list
134 if (ConfigPrivateData
->HiiHandle
!= NULL
) {
135 HiiRemovePackages (ConfigPrivateData
->HiiHandle
);
136 ConfigPrivateData
->HiiHandle
= NULL
;
140 // Uninstall HII Config Access Protocol
142 if (ConfigPrivateData
->DriverHandle
!= NULL
) {
143 gBS
->UninstallMultipleProtocolInterfaces (
144 ConfigPrivateData
->DriverHandle
,
145 &gEfiDevicePathProtocolGuid
,
146 &mRamDiskHiiVendorDevicePath
,
147 &gEfiHiiConfigAccessProtocolGuid
,
148 &ConfigPrivateData
->ConfigAccess
,
151 ConfigPrivateData
->DriverHandle
= NULL
;
154 FreePool (ConfigPrivateData
);
159 Unregister all registered RAM disks.
163 UnregisterAllRamDisks (
168 LIST_ENTRY
*NextEntry
;
169 RAM_DISK_PRIVATE_DATA
*PrivateData
;
171 if (!IsListEmpty(&RegisteredRamDisks
)) {
172 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
173 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
175 gBS
->UninstallMultipleProtocolInterfaces (
177 &gEfiBlockIoProtocolGuid
,
178 &PrivateData
->BlockIo
,
179 &gEfiBlockIo2ProtocolGuid
,
180 &PrivateData
->BlockIo2
,
181 &gEfiDevicePathProtocolGuid
,
182 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
186 RemoveEntryList (&PrivateData
->ThisInstance
);
188 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
190 // If a RAM disk is created within HII, then the RamDiskDxe driver
191 // driver is responsible for freeing the allocated memory for the
194 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
197 FreePool (PrivateData
->DevicePath
);
198 FreePool (PrivateData
);
205 This function allows a caller to extract the current configuration for one
206 or more named elements from the target driver.
208 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
209 @param[in] Request A null-terminated Unicode string in
210 <ConfigRequest> format.
211 @param[out] Progress On return, points to a character in the Request
212 string. Points to the string's null terminator if
213 request was successful. Points to the most recent
214 '&' before the first failing name/value pair (or
215 the beginning of the string if the failure is in
216 the first name/value pair) if the request was not
218 @param[out] Results A null-terminated Unicode string in
219 <ConfigAltResp> format which has all values filled
220 in for the names in the Request string. String to
221 be allocated by the called function.
223 @retval EFI_SUCCESS The Results is filled with the requested
225 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
226 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
227 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
233 RamDiskExtractConfig (
234 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
235 IN CONST EFI_STRING Request
,
236 OUT EFI_STRING
*Progress
,
237 OUT EFI_STRING
*Results
240 if (Progress
== NULL
|| Results
== NULL
) {
241 return EFI_INVALID_PARAMETER
;
244 return EFI_NOT_FOUND
;
249 This function processes the results of changes in configuration.
251 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
252 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
254 @param[out] Progress A pointer to a string filled in with the offset of
255 the most recent '&' before the first failing
256 name/value pair (or the beginning of the string if
257 the failure is in the first name/value pair) or
258 the terminating NULL if all was successful.
260 @retval EFI_SUCCESS The Results is processed successfully.
261 @retval EFI_INVALID_PARAMETER Configuration is NULL.
262 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
269 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
270 IN CONST EFI_STRING Configuration
,
271 OUT EFI_STRING
*Progress
274 if (Configuration
== NULL
|| Progress
== NULL
) {
275 return EFI_INVALID_PARAMETER
;
278 return EFI_NOT_FOUND
;
283 Allocate memory and register the RAM disk created within RamDiskDxe
286 @param[in] Size If creating raw, size of the RAM disk to create.
287 If creating from file, zero.
288 @param[in] FileHandle If creating raw, NULL. If creating from file, the
291 @retval EFI_SUCCESS RAM disk is created and registered.
292 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the
299 IN EFI_FILE_HANDLE FileHandle
306 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
307 RAM_DISK_PRIVATE_DATA
*PrivateData
;
308 EFI_FILE_INFO
*FileInformation
;
310 FileInformation
= NULL
;
312 if (FileHandle
!= NULL
) {
316 FileInformation
= FileInfo (FileHandle
);
317 if (NULL
== FileInformation
) {
320 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
323 L
"Not enough memory to get the file information!",
324 L
"Press ENTER to continue ...",
328 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
330 return EFI_OUT_OF_RESOURCES
;
334 // Update the size of RAM disk according to the file size.
336 Size
= FileInformation
->FileSize
;
339 if (Size
> (UINTN
) -1) {
342 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
345 L
"The given RAM disk size is too large!",
346 L
"Press ENTER to continue ...",
350 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
352 return EFI_OUT_OF_RESOURCES
;
355 StartingAddr
= (UINTN
) AllocatePool ((UINTN
) Size
);
356 if (0 == StartingAddr
) {
359 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
362 L
"Not enough memory to create the RAM disk!",
363 L
"Press ENTER to continue ...",
367 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
369 return EFI_OUT_OF_RESOURCES
;
372 if (FileHandle
!= NULL
) {
374 // Copy the file content to the RAM disk.
376 BufferSize
= (UINTN
) Size
;
380 (VOID
*)(UINTN
) StartingAddr
382 if (BufferSize
!= FileInformation
->FileSize
) {
385 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
388 L
"File content read error!",
389 L
"Press ENTER to continue ...",
393 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
395 return EFI_DEVICE_ERROR
;
400 // Register the newly created RAM disk.
402 Status
= RamDiskRegister (
405 &gEfiVirtualDiskGuid
,
409 if (EFI_ERROR (Status
)) {
412 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
415 L
"Fail to register the newly created RAM disk!",
416 L
"Press ENTER to continue ...",
420 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
426 // If RAM disk is created within HII, memory should be freed when the
427 // RAM disk is unregisterd.
429 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks
.BackLink
);
430 PrivateData
->CreateMethod
= RamDiskCreateHii
;
437 This function updates the registered RAM disks list on the main form.
439 @param[in, out] ConfigPrivate
440 Private data for configurating hii data for RAM
446 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
449 VOID
*StartOpCodeHandle
;
450 VOID
*EndOpCodeHandle
;
451 EFI_IFR_GUID_LABEL
*StartLabel
;
452 EFI_IFR_GUID_LABEL
*EndLabel
;
455 RAM_DISK_PRIVATE_DATA
*PrivateData
;
457 CHAR16 RamDiskStr
[128];
458 EFI_STRING_ID StringId
;
461 // Init OpCode Handle
463 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
464 ASSERT (StartOpCodeHandle
!= NULL
);
466 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
467 ASSERT (EndOpCodeHandle
!= NULL
);
470 // Create Hii Extend Label OpCode as the start opcode
472 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
476 sizeof (EFI_IFR_GUID_LABEL
)
478 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
479 StartLabel
->Number
= MAIN_LABEL_LIST_START
;
482 // Create Hii Extend Label OpCode as the end opcode
484 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
488 sizeof (EFI_IFR_GUID_LABEL
)
490 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
491 EndLabel
->Number
= MAIN_LABEL_LIST_END
;
494 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
495 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
496 PrivateData
->CheckBoxId
= (EFI_QUESTION_ID
)
497 (MAIN_CHECKBOX_QUESTION_ID_START
+ Index
);
499 // CheckBox is unchecked by default.
501 PrivateData
->CheckBoxChecked
= FALSE
;
507 L
" RAM Disk %d: [0x%lx, 0x%lx]\n",
509 PrivateData
->StartingAddr
,
510 PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
513 StringId
= HiiSetString (ConfigPrivate
->HiiHandle
, 0, RamDiskStr
, NULL
);
514 ASSERT (StringId
!= 0);
516 HiiCreateCheckBoxOpCode (
518 PrivateData
->CheckBoxId
,
522 STRING_TOKEN (STR_RAM_DISK_LIST_HELP
),
523 EFI_IFR_FLAG_CALLBACK
,
532 ConfigPrivate
->HiiHandle
,
533 &gRamDiskFormSetGuid
,
539 HiiFreeOpCodeHandle (StartOpCodeHandle
);
540 HiiFreeOpCodeHandle (EndOpCodeHandle
);
545 This function processes the results of changes in configuration.
547 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
548 @param[in] Action Specifies the type of action taken by the browser.
549 @param[in] QuestionId A unique value which is sent to the original
550 exporting driver so that it can identify the type
552 @param[in] Type The type of value for the question.
553 @param[in] Value A pointer to the data being sent to the original
555 @param[out] ActionRequest On return, points to the action requested by the
558 @retval EFI_SUCCESS The callback successfully handled the action.
559 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
560 variable and its data.
561 @retval EFI_DEVICE_ERROR The variable could not be saved.
562 @retval EFI_UNSUPPORTED The specified Action is not supported by the
569 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
570 IN EFI_BROWSER_ACTION Action
,
571 IN EFI_QUESTION_ID QuestionId
,
573 IN EFI_IFR_TYPE_VALUE
*Value
,
574 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
578 RAM_DISK_PRIVATE_DATA
*PrivateData
;
579 RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
;
580 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
581 EFI_FILE_HANDLE FileHandle
;
583 LIST_ENTRY
*NextEntry
;
585 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
586 return EFI_INVALID_PARAMETER
;
589 ConfigPrivate
= RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This
);
591 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
592 Status
= EFI_UNSUPPORTED
;
593 if (QuestionId
== CREATE_RAW_SIZE_QUESTION_ID
) {
594 Value
->u64
= EFI_PAGE_SIZE
;
595 ConfigPrivate
->ConfigStore
.Size
= EFI_PAGE_SIZE
;
596 Status
= EFI_SUCCESS
;
601 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
602 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
603 (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
)) {
604 return EFI_UNSUPPORTED
;
608 // Update the RAM disk list show at the main form first.
610 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
611 Status
= EFI_UNSUPPORTED
;
612 if (QuestionId
== MAIN_GOTO_FILE_EXPLORER_ID
) {
613 UpdateMainForm (ConfigPrivate
);
614 Status
= EFI_SUCCESS
;
619 Status
= EFI_SUCCESS
;
621 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
622 switch (QuestionId
) {
623 case MAIN_GOTO_FILE_EXPLORER_ID
:
624 Status
= ChooseFile (NULL
, NULL
, NULL
, &FileDevPath
);
625 if (EFI_ERROR (Status
)) {
629 if (FileDevPath
!= NULL
) {
633 Status
= OpenFileByDevicePath (
639 if (EFI_ERROR (Status
)) {
644 // Create from file, RAM disk size is zero. It will be updated
645 // according to the file size.
647 Status
= HiiCreateRamDisk (0, FileHandle
);
648 if (EFI_ERROR (Status
)) {
653 // Refresh the registered RAM disks list.
655 UpdateMainForm (ConfigPrivate
);
662 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
663 switch (QuestionId
) {
664 case MAIN_REMOVE_RD_QUESTION_ID
:
666 // Remove the selected RAM disks
668 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
669 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
670 if (PrivateData
->CheckBoxChecked
) {
672 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
677 UpdateMainForm (ConfigPrivate
);
679 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
682 case CREATE_RAW_SIZE_QUESTION_ID
:
683 ConfigPrivate
->ConfigStore
.Size
= Value
->u64
;
686 case CREATE_RAW_SUBMIT_QUESTION_ID
:
688 // Create raw, FileHandle is NULL.
690 Status
= HiiCreateRamDisk (ConfigPrivate
->ConfigStore
.Size
, NULL
);
691 if (EFI_ERROR (Status
)) {
696 // Refresh the registered RAM disks list.
698 UpdateMainForm (ConfigPrivate
);
700 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
703 case CREATE_RAW_DISCARD_QUESTION_ID
:
704 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
709 // QuestionIds for checkboxes
711 if ((QuestionId
>= MAIN_CHECKBOX_QUESTION_ID_START
) &&
712 (QuestionId
< CREATE_RAW_RAM_DISK_FORM_ID
)) {
713 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
714 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
715 if (PrivateData
->CheckBoxId
== QuestionId
) {
716 PrivateData
->CheckBoxChecked
= (BOOLEAN
) (Value
->u8
!= 0);