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
,
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)
52 This function publish the RAM disk configuration Form.
54 @param[in, out] ConfigPrivateData
55 Points to RAM disk configuration private data.
57 @retval EFI_SUCCESS HII Form is installed successfully.
58 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
59 @retval Others Other errors as indicated.
63 InstallRamDiskConfigForm (
64 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
68 EFI_HII_HANDLE HiiHandle
;
69 EFI_HANDLE DriverHandle
;
70 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
73 ConfigAccess
= &ConfigPrivateData
->ConfigAccess
;
74 Status
= gBS
->InstallMultipleProtocolInterfaces (
76 &gEfiDevicePathProtocolGuid
,
77 &mRamDiskHiiVendorDevicePath
,
78 &gEfiHiiConfigAccessProtocolGuid
,
82 if (EFI_ERROR (Status
)) {
86 ConfigPrivateData
->DriverHandle
= DriverHandle
;
89 // Publish the HII package list
91 HiiHandle
= HiiAddPackages (
98 if (HiiHandle
== NULL
) {
99 gBS
->UninstallMultipleProtocolInterfaces (
101 &gEfiDevicePathProtocolGuid
,
102 &mRamDiskHiiVendorDevicePath
,
103 &gEfiHiiConfigAccessProtocolGuid
,
107 return EFI_OUT_OF_RESOURCES
;
110 ConfigPrivateData
->HiiHandle
= HiiHandle
;
117 This function removes RAM disk configuration Form.
119 @param[in, out] ConfigPrivateData
120 Points to RAM disk configuration private data.
124 UninstallRamDiskConfigForm (
125 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivateData
129 // Uninstall HII package list
131 if (ConfigPrivateData
->HiiHandle
!= NULL
) {
132 HiiRemovePackages (ConfigPrivateData
->HiiHandle
);
133 ConfigPrivateData
->HiiHandle
= NULL
;
137 // Uninstall HII Config Access Protocol
139 if (ConfigPrivateData
->DriverHandle
!= NULL
) {
140 gBS
->UninstallMultipleProtocolInterfaces (
141 ConfigPrivateData
->DriverHandle
,
142 &gEfiDevicePathProtocolGuid
,
143 &mRamDiskHiiVendorDevicePath
,
144 &gEfiHiiConfigAccessProtocolGuid
,
145 &ConfigPrivateData
->ConfigAccess
,
148 ConfigPrivateData
->DriverHandle
= NULL
;
151 FreePool (ConfigPrivateData
);
156 Unregister all registered RAM disks.
160 UnregisterAllRamDisks (
165 LIST_ENTRY
*NextEntry
;
166 RAM_DISK_PRIVATE_DATA
*PrivateData
;
168 if (!IsListEmpty(&RegisteredRamDisks
)) {
169 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
170 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
172 gBS
->UninstallMultipleProtocolInterfaces (
174 &gEfiBlockIoProtocolGuid
,
175 &PrivateData
->BlockIo
,
176 &gEfiBlockIo2ProtocolGuid
,
177 &PrivateData
->BlockIo2
,
178 &gEfiDevicePathProtocolGuid
,
179 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
,
183 RemoveEntryList (&PrivateData
->ThisInstance
);
185 if (RamDiskCreateHii
== PrivateData
->CreateMethod
) {
187 // If a RAM disk is created within HII, then the RamDiskDxe driver
188 // driver is responsible for freeing the allocated memory for the
191 FreePool ((VOID
*)(UINTN
) PrivateData
->StartingAddr
);
194 FreePool (PrivateData
->DevicePath
);
195 FreePool (PrivateData
);
202 This function allows a caller to extract the current configuration for one
203 or more named elements from the target driver.
205 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
206 @param[in] Request A null-terminated Unicode string in
207 <ConfigRequest> format.
208 @param[out] Progress On return, points to a character in the Request
209 string. Points to the string's null terminator if
210 request was successful. Points to the most recent
211 '&' before the first failing name/value pair (or
212 the beginning of the string if the failure is in
213 the first name/value pair) if the request was not
215 @param[out] Results A null-terminated Unicode string in
216 <ConfigAltResp> format which has all values filled
217 in for the names in the Request string. String to
218 be allocated by the called function.
220 @retval EFI_SUCCESS The Results is filled with the requested
222 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
223 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
224 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
230 RamDiskExtractConfig (
231 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
232 IN CONST EFI_STRING Request
,
233 OUT EFI_STRING
*Progress
,
234 OUT EFI_STRING
*Results
239 RAM_DISK_CONFIGURATION
*Configuration
;
240 EFI_STRING ConfigRequest
;
241 EFI_STRING ConfigRequestHdr
;
242 RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
;
244 BOOLEAN AllocatedRequest
;
246 if (Progress
== NULL
|| Results
== NULL
) {
247 return EFI_INVALID_PARAMETER
;
251 if ((Request
!= NULL
) &&
252 !HiiIsConfigHdrMatch (Request
, &gRamDiskFormSetGuid
, mRamDiskStorageName
)) {
253 return EFI_NOT_FOUND
;
256 ConfigRequestHdr
= NULL
;
257 ConfigRequest
= NULL
;
258 AllocatedRequest
= FALSE
;
262 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
264 ConfigPrivate
= RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This
);
265 BufferSize
= sizeof (RAM_DISK_CONFIGURATION
);
266 Configuration
= AllocateZeroPool (BufferSize
);
267 if (Configuration
== NULL
) {
268 return EFI_OUT_OF_RESOURCES
;
271 ConfigRequest
= Request
;
272 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
274 // Request has no request element, construct full request string.
275 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
276 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
278 ConfigRequestHdr
= HiiConstructConfigHdr (
279 &gRamDiskFormSetGuid
,
281 ConfigPrivate
->DriverHandle
283 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
284 ConfigRequest
= AllocateZeroPool (Size
);
285 ASSERT (ConfigRequest
!= NULL
);
286 AllocatedRequest
= TRUE
;
287 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
288 FreePool (ConfigRequestHdr
);
291 Status
= gHiiConfigRouting
->BlockToConfig (
294 (UINT8
*) &Configuration
,
300 // Free the allocated config request string and RAM disk configuration data.
302 if (AllocatedRequest
) {
303 FreePool (ConfigRequest
);
304 ConfigRequest
= NULL
;
306 FreePool (Configuration
);
309 // Set Progress string to the original request string.
311 if (Request
== NULL
) {
313 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
314 *Progress
= Request
+ StrLen (Request
);
322 This function processes the results of changes in configuration.
324 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
325 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
327 @param[out] Progress A pointer to a string filled in with the offset of
328 the most recent '&' before the first failing
329 name/value pair (or the beginning of the string if
330 the failure is in the first name/value pair) or
331 the terminating NULL if all was successful.
333 @retval EFI_SUCCESS The Results is processed successfully.
334 @retval EFI_INVALID_PARAMETER Configuration is NULL.
335 @retval EFI_NOT_FOUND Routing data doesn't match any storage in
342 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
343 IN CONST EFI_STRING Configuration
,
344 OUT EFI_STRING
*Progress
347 if (Configuration
== NULL
|| Progress
== NULL
) {
348 return EFI_INVALID_PARAMETER
;
351 *Progress
= Configuration
;
352 if (!HiiIsConfigHdrMatch (Configuration
, &gRamDiskFormSetGuid
, mRamDiskStorageName
)) {
353 return EFI_NOT_FOUND
;
356 *Progress
= Configuration
+ StrLen (Configuration
);
363 Allocate memory and register the RAM disk created within RamDiskDxe
366 @param[in] Size If creating raw, size of the RAM disk to create.
367 If creating from file, zero.
368 @param[in] FileHandle If creating raw, NULL. If creating from file, the
371 @retval EFI_SUCCESS RAM disk is created and registered.
372 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the
379 IN EFI_FILE_HANDLE FileHandle
386 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
387 RAM_DISK_PRIVATE_DATA
*PrivateData
;
388 EFI_FILE_INFO
*FileInformation
;
390 FileInformation
= NULL
;
392 if (FileHandle
!= NULL
) {
396 FileInformation
= FileInfo (FileHandle
);
397 if (NULL
== FileInformation
) {
400 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
403 L
"Not enough memory to get the file information!",
404 L
"Press ENTER to continue ...",
408 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
410 return EFI_OUT_OF_RESOURCES
;
414 // Update the size of RAM disk according to the file size.
416 Size
= FileInformation
->FileSize
;
419 StartingAddr
= (UINTN
) AllocatePool ((UINTN
) Size
);
420 if (0 == StartingAddr
) {
423 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
426 L
"Not enough memory to create the RAM disk!",
427 L
"Press ENTER to continue ...",
431 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
433 return EFI_OUT_OF_RESOURCES
;
436 if (FileHandle
!= NULL
) {
438 // Copy the file content to the RAM disk.
440 BufferSize
= (UINTN
) Size
;
444 (VOID
*)(UINTN
) StartingAddr
446 if (BufferSize
!= FileInformation
->FileSize
) {
449 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
452 L
"File content read error!",
453 L
"Press ENTER to continue ...",
457 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
459 return EFI_DEVICE_ERROR
;
464 // Register the newly created RAM disk.
466 Status
= RamDiskRegister (
469 &gEfiVirtualDiskGuid
,
473 if (EFI_ERROR (Status
)) {
476 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
479 L
"Fail to register the newly created RAM disk!",
480 L
"Press ENTER to continue ...",
484 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
490 // If RAM disk is created within HII, memory should be freed when the
491 // RAM disk is unregisterd.
493 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks
.BackLink
);
494 PrivateData
->CreateMethod
= RamDiskCreateHii
;
501 This function updates the registered RAM disks list on the main form.
503 @param[in, out] ConfigPrivate
504 Private data for configurating hii data for RAM
510 IN OUT RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
513 VOID
*StartOpCodeHandle
;
514 VOID
*EndOpCodeHandle
;
515 EFI_IFR_GUID_LABEL
*StartLabel
;
516 EFI_IFR_GUID_LABEL
*EndLabel
;
519 RAM_DISK_PRIVATE_DATA
*PrivateData
;
521 CHAR16 RamDiskStr
[128];
522 EFI_STRING_ID StringId
;
525 // Init OpCode Handle
527 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
528 ASSERT (StartOpCodeHandle
!= NULL
);
530 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
531 ASSERT (EndOpCodeHandle
!= NULL
);
534 // Create Hii Extend Label OpCode as the start opcode
536 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
540 sizeof (EFI_IFR_GUID_LABEL
)
542 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
543 StartLabel
->Number
= MAIN_LABEL_LIST_START
;
546 // Create Hii Extend Label OpCode as the end opcode
548 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
552 sizeof (EFI_IFR_GUID_LABEL
)
554 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
555 EndLabel
->Number
= MAIN_LABEL_LIST_END
;
558 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
559 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
560 PrivateData
->CheckBoxId
= (EFI_QUESTION_ID
)
561 (MAIN_CHECKBOX_QUESTION_ID_START
+ Index
);
563 // CheckBox is unchecked by default.
565 PrivateData
->CheckBoxChecked
= FALSE
;
571 L
" RAM Disk %d: [0x%lx, 0x%lx]\n",
573 PrivateData
->StartingAddr
,
574 PrivateData
->StartingAddr
+ PrivateData
->Size
- 1
577 StringId
= HiiSetString (ConfigPrivate
->HiiHandle
, 0, RamDiskStr
, NULL
);
578 ASSERT (StringId
!= 0);
580 HiiCreateCheckBoxOpCode (
582 PrivateData
->CheckBoxId
,
586 STRING_TOKEN (STR_RAM_DISK_LIST_HELP
),
587 EFI_IFR_FLAG_CALLBACK
,
596 ConfigPrivate
->HiiHandle
,
597 &gRamDiskFormSetGuid
,
603 HiiFreeOpCodeHandle (StartOpCodeHandle
);
604 HiiFreeOpCodeHandle (EndOpCodeHandle
);
609 This function processes the results of changes in configuration.
611 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
612 @param[in] Action Specifies the type of action taken by the browser.
613 @param[in] QuestionId A unique value which is sent to the original
614 exporting driver so that it can identify the type
616 @param[in] Type The type of value for the question.
617 @param[in] Value A pointer to the data being sent to the original
619 @param[out] ActionRequest On return, points to the action requested by the
622 @retval EFI_SUCCESS The callback successfully handled the action.
623 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
624 variable and its data.
625 @retval EFI_DEVICE_ERROR The variable could not be saved.
626 @retval EFI_UNSUPPORTED The specified Action is not supported by the
633 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
634 IN EFI_BROWSER_ACTION Action
,
635 IN EFI_QUESTION_ID QuestionId
,
637 IN EFI_IFR_TYPE_VALUE
*Value
,
638 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
642 RAM_DISK_PRIVATE_DATA
*PrivateData
;
643 RAM_DISK_CONFIG_PRIVATE_DATA
*ConfigPrivate
;
644 RAM_DISK_CONFIGURATION
*Configuration
;
645 EFI_DEVICE_PATH_PROTOCOL
*FileDevPath
;
646 EFI_FILE_HANDLE FileHandle
;
648 LIST_ENTRY
*NextEntry
;
650 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
651 return EFI_INVALID_PARAMETER
;
654 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
655 Status
= EFI_UNSUPPORTED
;
656 if (QuestionId
== CREATE_RAW_SIZE_QUESTION_ID
) {
657 Value
->u64
= EFI_PAGE_SIZE
;
658 Status
= EFI_SUCCESS
;
663 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
664 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
665 (Action
!= EFI_BROWSER_ACTION_FORM_OPEN
)) {
666 return EFI_UNSUPPORTED
;
669 ConfigPrivate
= RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This
);
672 // Update the RAM disk list show at the main form first.
674 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
675 Status
= EFI_UNSUPPORTED
;
676 if (QuestionId
== MAIN_GOTO_FILE_EXPLORER_ID
) {
677 UpdateMainForm (ConfigPrivate
);
678 Status
= EFI_SUCCESS
;
686 Configuration
= AllocateZeroPool (sizeof (RAM_DISK_CONFIGURATION
));
687 if (Configuration
== NULL
) {
688 return EFI_OUT_OF_RESOURCES
;
691 Status
= EFI_SUCCESS
;
694 &gRamDiskFormSetGuid
,
696 sizeof (RAM_DISK_CONFIGURATION
),
697 (UINT8
*) Configuration
700 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
701 switch (QuestionId
) {
702 case MAIN_GOTO_FILE_EXPLORER_ID
:
703 Status
= ChooseFile (NULL
, NULL
, NULL
, &FileDevPath
);
704 if (EFI_ERROR (Status
)) {
708 if (FileDevPath
!= NULL
) {
712 Status
= OpenFileByDevicePath (
718 if (EFI_ERROR (Status
)) {
723 // Create from file, RAM disk size is zero. It will be updated
724 // according to the file size.
726 Status
= HiiCreateRamDisk (0, FileHandle
);
727 if (EFI_ERROR (Status
)) {
732 // Refresh the registered RAM disks list.
734 UpdateMainForm (ConfigPrivate
);
737 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
743 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
744 switch (QuestionId
) {
745 case MAIN_REMOVE_RD_QUESTION_ID
:
747 // Remove the selected RAM disks
749 EFI_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &RegisteredRamDisks
) {
750 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
751 if (PrivateData
->CheckBoxChecked
) {
753 (EFI_DEVICE_PATH_PROTOCOL
*) PrivateData
->DevicePath
758 UpdateMainForm (ConfigPrivate
);
760 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
763 case CREATE_RAW_SUBMIT_QUESTION_ID
:
765 // Create raw, FileHandle is NULL.
767 Status
= HiiCreateRamDisk (Configuration
->Size
, NULL
);
768 if (EFI_ERROR (Status
)) {
773 // Refresh the registered RAM disks list.
775 UpdateMainForm (ConfigPrivate
);
777 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
780 case CREATE_RAW_DISCARD_QUESTION_ID
:
781 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
786 // QuestionIds for checkboxes
788 if ((QuestionId
>= MAIN_CHECKBOX_QUESTION_ID_START
) &&
789 (QuestionId
< CREATE_RAW_RAM_DISK_FORM_ID
)) {
790 EFI_LIST_FOR_EACH (Entry
, &RegisteredRamDisks
) {
791 PrivateData
= RAM_DISK_PRIVATE_FROM_THIS (Entry
);
792 if (PrivateData
->CheckBoxId
== QuestionId
) {
793 PrivateData
->CheckBoxChecked
= (BOOLEAN
) (Value
->u8
!= 0);
801 if (!EFI_ERROR (Status
)) {
803 &gRamDiskFormSetGuid
,
805 sizeof (RAM_DISK_CONFIGURATION
),
806 (UINT8
*) Configuration
,
810 FreePool (Configuration
);