• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   HII Config Access protocol implementation of RamDiskDxe driver.
3 
4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5   (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "RamDiskImpl.h"
17 
18 CHAR16  mRamDiskStorageName[] = L"RAM_DISK_CONFIGURATION";
19 
20 RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate = {
21   RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE,
22   {
23     EFI_PAGE_SIZE,
24     RAM_DISK_BOOT_SERVICE_DATA_MEMORY
25   },
26   {
27     RamDiskExtractConfig,
28     RamDiskRouteConfig,
29     RamDiskCallback
30   }
31 };
32 
33 HII_VENDOR_DEVICE_PATH       mRamDiskHiiVendorDevicePath = {
34   {
35     {
36       HARDWARE_DEVICE_PATH,
37       HW_VENDOR_DP,
38       {
39         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
40         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
41       }
42     },
43     RAM_DISK_FORM_SET_GUID
44   },
45   {
46     END_DEVICE_PATH_TYPE,
47     END_ENTIRE_DEVICE_PATH_SUBTYPE,
48     {
49       (UINT8) (END_DEVICE_PATH_LENGTH),
50       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
51     }
52   }
53 };
54 
55 
56 /**
57   This function publish the RAM disk configuration Form.
58 
59   @param[in, out]  ConfigPrivateData
60                              Points to RAM disk configuration private data.
61 
62   @retval EFI_SUCCESS             HII Form is installed successfully.
63   @retval EFI_OUT_OF_RESOURCES    Not enough resource for HII Form installation.
64   @retval Others                  Other errors as indicated.
65 
66 **/
67 EFI_STATUS
InstallRamDiskConfigForm(IN OUT RAM_DISK_CONFIG_PRIVATE_DATA * ConfigPrivateData)68 InstallRamDiskConfigForm (
69   IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
70   )
71 {
72   EFI_STATUS                      Status;
73   EFI_HII_HANDLE                  HiiHandle;
74   EFI_HANDLE                      DriverHandle;
75   EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
76 
77   DriverHandle = NULL;
78   ConfigAccess = &ConfigPrivateData->ConfigAccess;
79   Status = gBS->InstallMultipleProtocolInterfaces (
80                   &DriverHandle,
81                   &gEfiDevicePathProtocolGuid,
82                   &mRamDiskHiiVendorDevicePath,
83                   &gEfiHiiConfigAccessProtocolGuid,
84                   ConfigAccess,
85                   NULL
86                   );
87   if (EFI_ERROR (Status)) {
88     return Status;
89   }
90 
91   ConfigPrivateData->DriverHandle = DriverHandle;
92 
93   //
94   // Publish the HII package list
95   //
96   HiiHandle = HiiAddPackages (
97                 &gRamDiskFormSetGuid,
98                 DriverHandle,
99                 RamDiskDxeStrings,
100                 RamDiskHiiBin,
101                 NULL
102                 );
103   if (HiiHandle == NULL) {
104     gBS->UninstallMultipleProtocolInterfaces (
105            DriverHandle,
106            &gEfiDevicePathProtocolGuid,
107            &mRamDiskHiiVendorDevicePath,
108            &gEfiHiiConfigAccessProtocolGuid,
109            ConfigAccess,
110            NULL
111            );
112     return EFI_OUT_OF_RESOURCES;
113   }
114 
115   ConfigPrivateData->HiiHandle = HiiHandle;
116 
117   return EFI_SUCCESS;
118 }
119 
120 
121 /**
122   This function removes RAM disk configuration Form.
123 
124   @param[in, out]  ConfigPrivateData
125                              Points to RAM disk configuration private data.
126 
127 **/
128 VOID
UninstallRamDiskConfigForm(IN OUT RAM_DISK_CONFIG_PRIVATE_DATA * ConfigPrivateData)129 UninstallRamDiskConfigForm (
130   IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
131   )
132 {
133   //
134   // Uninstall HII package list
135   //
136   if (ConfigPrivateData->HiiHandle != NULL) {
137     HiiRemovePackages (ConfigPrivateData->HiiHandle);
138     ConfigPrivateData->HiiHandle = NULL;
139   }
140 
141   //
142   // Uninstall HII Config Access Protocol
143   //
144   if (ConfigPrivateData->DriverHandle != NULL) {
145     gBS->UninstallMultipleProtocolInterfaces (
146            ConfigPrivateData->DriverHandle,
147            &gEfiDevicePathProtocolGuid,
148            &mRamDiskHiiVendorDevicePath,
149            &gEfiHiiConfigAccessProtocolGuid,
150            &ConfigPrivateData->ConfigAccess,
151            NULL
152            );
153     ConfigPrivateData->DriverHandle = NULL;
154   }
155 
156   FreePool (ConfigPrivateData);
157 }
158 
159 
160 /**
161   Unregister all registered RAM disks.
162 
163 **/
164 VOID
UnregisterAllRamDisks(VOID)165 UnregisterAllRamDisks (
166   VOID
167   )
168 {
169   LIST_ENTRY                      *Entry;
170   LIST_ENTRY                      *NextEntry;
171   RAM_DISK_PRIVATE_DATA           *PrivateData;
172 
173   if (!IsListEmpty(&RegisteredRamDisks)) {
174     EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
175       PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
176 
177       gBS->UninstallMultipleProtocolInterfaces (
178              PrivateData->Handle,
179              &gEfiBlockIoProtocolGuid,
180              &PrivateData->BlockIo,
181              &gEfiBlockIo2ProtocolGuid,
182              &PrivateData->BlockIo2,
183              &gEfiDevicePathProtocolGuid,
184              (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath,
185              NULL
186              );
187 
188       RemoveEntryList (&PrivateData->ThisInstance);
189 
190       if (RamDiskCreateHii == PrivateData->CreateMethod) {
191         //
192         // If a RAM disk is created within HII, then the RamDiskDxe driver
193         // driver is responsible for freeing the allocated memory for the
194         // RAM disk.
195         //
196         FreePool ((VOID *)(UINTN) PrivateData->StartingAddr);
197       }
198 
199       FreePool (PrivateData->DevicePath);
200       FreePool (PrivateData);
201     }
202   }
203 }
204 
205 
206 /**
207   This function allows a caller to extract the current configuration for one
208   or more named elements from the target driver.
209 
210   @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
211   @param[in]  Request        A null-terminated Unicode string in
212                              <ConfigRequest> format.
213   @param[out] Progress       On return, points to a character in the Request
214                              string. Points to the string's null terminator if
215                              request was successful. Points to the most recent
216                              '&' before the first failing name/value pair (or
217                              the beginning of the string if the failure is in
218                              the first name/value pair) if the request was not
219                              successful.
220   @param[out] Results        A null-terminated Unicode string in
221                              <ConfigAltResp> format which has all values filled
222                              in for the names in the Request string. String to
223                              be allocated by the called function.
224 
225   @retval EFI_SUCCESS             The Results is filled with the requested
226                                   values.
227   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the results.
228   @retval EFI_INVALID_PARAMETER   Request is illegal syntax, or unknown name.
229   @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
230                                   this driver.
231 
232 **/
233 EFI_STATUS
234 EFIAPI
RamDiskExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)235 RamDiskExtractConfig (
236   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
237   IN CONST EFI_STRING                       Request,
238        OUT EFI_STRING                       *Progress,
239        OUT EFI_STRING                       *Results
240   )
241 {
242   if (Progress == NULL || Results == NULL) {
243     return EFI_INVALID_PARAMETER;
244   }
245   *Progress = Request;
246   return EFI_NOT_FOUND;
247 }
248 
249 
250 /**
251   This function processes the results of changes in configuration.
252 
253   @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
254   @param[in]  Configuration  A null-terminated Unicode string in <ConfigResp>
255                              format.
256   @param[out] Progress       A pointer to a string filled in with the offset of
257                              the most recent '&' before the first failing
258                              name/value pair (or the beginning of the string if
259                              the failure is in the first name/value pair) or
260                              the terminating NULL if all was successful.
261 
262   @retval EFI_SUCCESS             The Results is processed successfully.
263   @retval EFI_INVALID_PARAMETER   Configuration is NULL.
264   @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
265                                   this driver.
266 
267 **/
268 EFI_STATUS
269 EFIAPI
RamDiskRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)270 RamDiskRouteConfig (
271   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
272   IN CONST EFI_STRING                       Configuration,
273        OUT EFI_STRING                       *Progress
274   )
275 {
276   if (Configuration == NULL || Progress == NULL) {
277     return EFI_INVALID_PARAMETER;
278   }
279 
280   return EFI_NOT_FOUND;
281 }
282 
283 
284 /**
285   Allocate memory and register the RAM disk created within RamDiskDxe
286   driver HII.
287 
288   @param[in] Size            If creating raw, size of the RAM disk to create.
289                              If creating from file, zero.
290   @param[in] FileHandle      If creating raw, NULL. If creating from file, the
291                              file handle.
292   @param[in] MemoryType      Type of memory to be used to create RAM Disk.
293 
294   @retval EFI_SUCCESS             RAM disk is created and registered.
295   @retval EFI_OUT_OF_RESOURCES    Not enough storage is available to match the
296                                   size required.
297 
298 **/
299 EFI_STATUS
HiiCreateRamDisk(IN UINT64 Size,IN EFI_FILE_HANDLE FileHandle,IN UINT8 MemoryType)300 HiiCreateRamDisk (
301   IN UINT64                                 Size,
302   IN EFI_FILE_HANDLE                        FileHandle,
303   IN UINT8                                  MemoryType
304   )
305 {
306   EFI_STATUS                      Status;
307   UINTN                           BufferSize;
308   UINT64                          *StartingAddr;
309   EFI_INPUT_KEY                   Key;
310   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
311   RAM_DISK_PRIVATE_DATA           *PrivateData;
312   EFI_FILE_INFO                   *FileInformation;
313 
314   FileInformation = NULL;
315   StartingAddr    = NULL;
316 
317   if (FileHandle != NULL) {
318     //
319     // Create from file.
320     //
321     FileInformation = FileInfo (FileHandle);
322     if (NULL == FileInformation) {
323       do {
324         CreatePopUp (
325           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
326           &Key,
327           L"",
328           L"Not enough memory to get the file information!",
329           L"Press ENTER to continue ...",
330           L"",
331           NULL
332           );
333       } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
334 
335       return EFI_OUT_OF_RESOURCES;
336     }
337 
338     //
339     // Update the size of RAM disk according to the file size.
340     //
341     Size = FileInformation->FileSize;
342   }
343 
344   if (Size > (UINTN) -1) {
345     do {
346       CreatePopUp (
347         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
348         &Key,
349         L"",
350         L"The given RAM disk size is too large!",
351         L"Press ENTER to continue ...",
352         L"",
353         NULL
354         );
355     } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
356 
357     return EFI_OUT_OF_RESOURCES;
358   }
359 
360   if (MemoryType == RAM_DISK_BOOT_SERVICE_DATA_MEMORY) {
361     Status = gBS->AllocatePool (
362                     EfiBootServicesData,
363                     (UINTN)Size,
364                     (VOID**)&StartingAddr
365                     );
366   } else if (MemoryType == RAM_DISK_RESERVED_MEMORY) {
367     Status = gBS->AllocatePool (
368                     EfiReservedMemoryType,
369                     (UINTN)Size,
370                     (VOID**)&StartingAddr
371                     );
372   } else {
373     Status = EFI_INVALID_PARAMETER;
374   }
375 
376   if ((StartingAddr == NULL) || EFI_ERROR(Status)) {
377     do {
378       CreatePopUp (
379         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
380         &Key,
381         L"",
382         L"Not enough memory to create the RAM disk!",
383         L"Press ENTER to continue ...",
384         L"",
385         NULL
386         );
387     } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
388 
389     return EFI_OUT_OF_RESOURCES;
390   }
391 
392   if (FileHandle != NULL) {
393     //
394     // Copy the file content to the RAM disk.
395     //
396     BufferSize = (UINTN) Size;
397     FileHandle->Read (
398                   FileHandle,
399                   &BufferSize,
400                   (VOID *)(UINTN) StartingAddr
401                   );
402     if (BufferSize != FileInformation->FileSize) {
403       do {
404         CreatePopUp (
405           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
406           &Key,
407           L"",
408           L"File content read error!",
409           L"Press ENTER to continue ...",
410           L"",
411           NULL
412           );
413       } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
414 
415       return EFI_DEVICE_ERROR;
416     }
417   }
418 
419   //
420   // Register the newly created RAM disk.
421   //
422   Status = RamDiskRegister (
423              ((UINT64)(UINTN) StartingAddr),
424              Size,
425              &gEfiVirtualDiskGuid,
426              NULL,
427              &DevicePath
428              );
429   if (EFI_ERROR (Status)) {
430     do {
431       CreatePopUp (
432         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
433         &Key,
434         L"",
435         L"Fail to register the newly created RAM disk!",
436         L"Press ENTER to continue ...",
437         L"",
438         NULL
439         );
440     } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
441 
442     return Status;
443   }
444 
445   //
446   // If RAM disk is created within HII, memory should be freed when the
447   // RAM disk is unregisterd.
448   //
449   PrivateData = RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks.BackLink);
450   PrivateData->CreateMethod = RamDiskCreateHii;
451 
452   return EFI_SUCCESS;
453 }
454 
455 
456 /**
457   This function updates the registered RAM disks list on the main form.
458 
459   @param[in, out] ConfigPrivate
460                              Private data for configurating hii data for RAM
461                              disks.
462 
463 **/
464 VOID
UpdateMainForm(IN OUT RAM_DISK_CONFIG_PRIVATE_DATA * ConfigPrivate)465 UpdateMainForm (
466   IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivate
467   )
468 {
469   VOID                      *StartOpCodeHandle;
470   VOID                      *EndOpCodeHandle;
471   EFI_IFR_GUID_LABEL        *StartLabel;
472   EFI_IFR_GUID_LABEL        *EndLabel;
473   LIST_ENTRY                *Entry;
474   UINTN                     Index;
475   RAM_DISK_PRIVATE_DATA     *PrivateData;
476   CHAR16                    *String;
477   CHAR16                    RamDiskStr[128];
478   EFI_STRING_ID             StringId;
479 
480   //
481   // Init OpCode Handle
482   //
483   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
484   ASSERT (StartOpCodeHandle != NULL);
485 
486   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
487   ASSERT (EndOpCodeHandle != NULL);
488 
489   //
490   // Create Hii Extend Label OpCode as the start opcode
491   //
492   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
493                                         StartOpCodeHandle,
494                                         &gEfiIfrTianoGuid,
495                                         NULL,
496                                         sizeof (EFI_IFR_GUID_LABEL)
497                                         );
498   StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
499   StartLabel->Number       = MAIN_LABEL_LIST_START;
500 
501   //
502   // Create Hii Extend Label OpCode as the end opcode
503   //
504   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
505                                       EndOpCodeHandle,
506                                       &gEfiIfrTianoGuid,
507                                       NULL,
508                                       sizeof (EFI_IFR_GUID_LABEL)
509                                       );
510   EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
511   EndLabel->Number       = MAIN_LABEL_LIST_END;
512 
513   Index = 0;
514   EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
515     PrivateData                  = RAM_DISK_PRIVATE_FROM_THIS (Entry);
516     PrivateData->CheckBoxId      = (EFI_QUESTION_ID)
517                                    (MAIN_CHECKBOX_QUESTION_ID_START + Index);
518     //
519     // CheckBox is unchecked by default.
520     //
521     PrivateData->CheckBoxChecked = FALSE;
522     String                       = RamDiskStr;
523 
524     UnicodeSPrint (
525       String,
526       sizeof (RamDiskStr),
527       L"  RAM Disk %d: [0x%lx, 0x%lx]\n",
528       Index,
529       PrivateData->StartingAddr,
530       PrivateData->StartingAddr + PrivateData->Size - 1
531       );
532 
533     StringId = HiiSetString (ConfigPrivate->HiiHandle, 0, RamDiskStr, NULL);
534     ASSERT (StringId != 0);
535 
536     HiiCreateCheckBoxOpCode (
537       StartOpCodeHandle,
538       PrivateData->CheckBoxId,
539       0,
540       0,
541       StringId,
542       STRING_TOKEN (STR_RAM_DISK_LIST_HELP),
543       EFI_IFR_FLAG_CALLBACK,
544       0,
545       NULL
546       );
547 
548     Index++;
549   }
550 
551   HiiUpdateForm (
552     ConfigPrivate->HiiHandle,
553     &gRamDiskFormSetGuid,
554     MAIN_FORM_ID,
555     StartOpCodeHandle,
556     EndOpCodeHandle
557     );
558 
559   HiiFreeOpCodeHandle (StartOpCodeHandle);
560   HiiFreeOpCodeHandle (EndOpCodeHandle);
561 }
562 
563 
564 /**
565   This function processes the results of changes in configuration.
566 
567   @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
568   @param[in]  Action         Specifies the type of action taken by the browser.
569   @param[in]  QuestionId     A unique value which is sent to the original
570                              exporting driver so that it can identify the type
571                              of data to expect.
572   @param[in]  Type           The type of value for the question.
573   @param[in]  Value          A pointer to the data being sent to the original
574                              exporting driver.
575   @param[out] ActionRequest  On return, points to the action requested by the
576                              callback function.
577 
578   @retval EFI_SUCCESS             The callback successfully handled the action.
579   @retval EFI_OUT_OF_RESOURCES    Not enough storage is available to hold the
580                                   variable and its data.
581   @retval EFI_DEVICE_ERROR        The variable could not be saved.
582   @retval EFI_UNSUPPORTED         The specified Action is not supported by the
583                                   callback.
584 
585 **/
586 EFI_STATUS
587 EFIAPI
RamDiskCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)588 RamDiskCallback (
589   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
590   IN     EFI_BROWSER_ACTION                 Action,
591   IN     EFI_QUESTION_ID                    QuestionId,
592   IN     UINT8                              Type,
593   IN     EFI_IFR_TYPE_VALUE                 *Value,
594      OUT EFI_BROWSER_ACTION_REQUEST         *ActionRequest
595   )
596 {
597   EFI_STATUS                      Status;
598   RAM_DISK_PRIVATE_DATA           *PrivateData;
599   RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
600   EFI_DEVICE_PATH_PROTOCOL        *FileDevPath;
601   EFI_FILE_HANDLE                 FileHandle;
602   LIST_ENTRY                      *Entry;
603   LIST_ENTRY                      *NextEntry;
604 
605   if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
606     return EFI_INVALID_PARAMETER;
607   }
608 
609   ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This);
610 
611   if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
612     Status = EFI_UNSUPPORTED;
613     if (QuestionId == CREATE_RAW_SIZE_QUESTION_ID) {
614       Value->u64 = EFI_PAGE_SIZE;
615       ConfigPrivate->ConfigStore.Size = EFI_PAGE_SIZE;
616       Status = EFI_SUCCESS;
617     } else if (QuestionId == CREATE_RAW_MEMORY_TYPE_QUESTION_ID) {
618       Value->u8 = RAM_DISK_BOOT_SERVICE_DATA_MEMORY;
619       ConfigPrivate->ConfigStore.MemType = RAM_DISK_BOOT_SERVICE_DATA_MEMORY;
620       Status = EFI_SUCCESS;
621     }
622     return Status;
623   }
624 
625   if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
626       (Action != EFI_BROWSER_ACTION_CHANGING) &&
627       (Action != EFI_BROWSER_ACTION_FORM_OPEN)) {
628     return EFI_UNSUPPORTED;
629   }
630 
631   //
632   // Update the RAM disk list show at the main form first.
633   //
634   if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
635     Status = EFI_UNSUPPORTED;
636     if (QuestionId == MAIN_GOTO_FILE_EXPLORER_ID) {
637       UpdateMainForm (ConfigPrivate);
638       Status = EFI_SUCCESS;
639     }
640     return Status;
641   }
642 
643   Status = EFI_SUCCESS;
644 
645   if (Action == EFI_BROWSER_ACTION_CHANGING) {
646     switch (QuestionId) {
647     case MAIN_GOTO_FILE_EXPLORER_ID:
648       Status = ChooseFile (NULL, NULL, NULL, &FileDevPath);
649       if (EFI_ERROR (Status)) {
650         break;
651       }
652 
653       if (FileDevPath != NULL) {
654         //
655         // Open the file.
656         //
657         Status = OpenFileByDevicePath (
658                    &FileDevPath,
659                    &FileHandle,
660                    EFI_FILE_MODE_READ,
661                    0
662                    );
663         if (EFI_ERROR (Status)) {
664           break;
665         }
666 
667         //
668         // Create from file, RAM disk size is zero. It will be updated
669         // according to the file size.
670         //
671         Status = HiiCreateRamDisk (
672                    0,
673                    FileHandle,
674                    ConfigPrivate->ConfigStore.MemType
675                    );
676         if (EFI_ERROR (Status)) {
677           break;
678         }
679 
680         //
681         // Refresh the registered RAM disks list.
682         //
683         UpdateMainForm (ConfigPrivate);
684       }
685       break;
686 
687     default:
688       break;
689     }
690   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
691     switch (QuestionId) {
692     case MAIN_REMOVE_RD_QUESTION_ID:
693       //
694       // Remove the selected RAM disks
695       //
696       EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
697         PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
698         if (PrivateData->CheckBoxChecked) {
699           RamDiskUnregister (
700             (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath
701             );
702         }
703       }
704 
705       UpdateMainForm (ConfigPrivate);
706 
707       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
708       break;
709 
710     case CREATE_RAW_SIZE_QUESTION_ID:
711       ConfigPrivate->ConfigStore.Size = Value->u64;
712       break;
713 
714     case CREATE_RAW_MEMORY_TYPE_QUESTION_ID:
715       ConfigPrivate->ConfigStore.MemType = Value->u8;
716       break;
717 
718     case CREATE_RAW_SUBMIT_QUESTION_ID:
719       //
720       // Create raw, FileHandle is NULL.
721       //
722       Status = HiiCreateRamDisk (
723                  ConfigPrivate->ConfigStore.Size,
724                  NULL,
725                  ConfigPrivate->ConfigStore.MemType
726                  );
727       if (EFI_ERROR (Status)) {
728         break;
729       }
730 
731       //
732       // Refresh the registered RAM disks list.
733       //
734       UpdateMainForm (ConfigPrivate);
735 
736       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
737       break;
738 
739     case CREATE_RAW_DISCARD_QUESTION_ID:
740       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
741       break;
742 
743     default:
744       //
745       // QuestionIds for checkboxes
746       //
747       if ((QuestionId >= MAIN_CHECKBOX_QUESTION_ID_START) &&
748           (QuestionId < CREATE_RAW_RAM_DISK_FORM_ID)) {
749         EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
750           PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
751           if (PrivateData->CheckBoxId == QuestionId) {
752             PrivateData->CheckBoxChecked = (BOOLEAN) (Value->u8 != 0);
753           }
754         }
755       }
756       break;
757     }
758   }
759 
760   return EFI_SUCCESS;
761 }
762