newline added at end
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / Variable.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   Variable.c\r
15 \r
16 Abstract:\r
17 \r
18   Variable operation that will be used by BootMaint\r
19 \r
20 --*/\r
21 \r
22 #include "Generic/Bds.h"\r
23 #include "BootMaint.h"\r
24 #include "BdsPlatform.h"\r
25 \r
26 EFI_STATUS\r
27 Var_DelBootOption (\r
28   VOID\r
29   )\r
30 /*++\r
31 \r
32 Routine Description:\r
33   Delete Boot Option that represent a Deleted state in BootOptionMenu.\r
34   After deleting this boot option, call Var_ChangeBootOrder to\r
35   make sure BootOrder is in valid state.\r
36   \r
37 Arguments:\r
38   LoadOption -- Pointer to the boot option that to be deleted\r
39 \r
40 Returns:\r
41   EFI_SUCCESS\r
42   Others\r
43   \r
44 --*/\r
45 {\r
46   BM_MENU_ENTRY   *NewMenuEntry;\r
47   BM_LOAD_CONTEXT *NewLoadContext;\r
48 \r
49   UINT16          BootString[10];\r
50   EFI_STATUS      Status;\r
51   UINTN           Index;\r
52   UINTN           Index2;\r
53 \r
54   Status  = EFI_SUCCESS;\r
55   Index2  = 0;\r
56   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
57     NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2));\r
58     if (NULL == NewMenuEntry) {\r
59       return EFI_NOT_FOUND;\r
60     }\r
61 \r
62     NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
63     if (!NewLoadContext->Deleted) {\r
64       continue;\r
65     }\r
66 \r
67     UnicodeSPrint (\r
68       BootString,\r
69       sizeof (BootString),\r
70       L"Boot%04x",\r
71       NewMenuEntry->OptionNumber\r
72       );\r
73 \r
74     EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid);\r
75     Index2++;\r
76     //\r
77     // If current Load Option is the same as BootNext,\r
78     // must delete BootNext in order to make sure\r
79     // there will be no panic on next boot\r
80     //\r
81     if (NewLoadContext->IsBootNext) {\r
82       EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
83     }\r
84 \r
85     RemoveEntryList (&NewMenuEntry->Link);\r
86     BOpt_DestroyMenuEntry (NewMenuEntry);\r
87     NewMenuEntry = NULL;\r
88   }\r
89 \r
90   BootOptionMenu.MenuNumber -= Index2;\r
91 \r
92   Status = Var_ChangeBootOrder ();\r
93   return Status;\r
94 }\r
95 \r
96 EFI_STATUS\r
97 Var_ChangeBootOrder (\r
98   VOID\r
99   )\r
100 /*++\r
101 \r
102 Routine Description:\r
103   After any operation on Boot####, there will be a discrepancy in BootOrder.\r
104   Since some are missing but in BootOrder, while some are present but are \r
105   not reflected by BootOrder. Then a function rebuild BootOrder from \r
106   scratch by content from BootOptionMenu is needed.\r
107   \r
108 Arguments:\r
109 \r
110 Returns:\r
111   EFI_SUCCESS\r
112   Others\r
113   \r
114 --*/\r
115 {\r
116 \r
117   EFI_STATUS    Status;\r
118   BM_MENU_ENTRY *NewMenuEntry;\r
119   UINT16        *BootOrderList;\r
120   UINT16        *BootOrderListPtr;\r
121   UINTN         BootOrderListSize;\r
122   UINTN         Index;\r
123 \r
124   BootOrderList     = NULL;\r
125   BootOrderListSize = 0;\r
126 \r
127   //\r
128   // First check whether BootOrder is present in current configuration\r
129   //\r
130   BootOrderList = BdsLibGetVariableAndSize (\r
131                     L"BootOrder",\r
132                     &gEfiGlobalVariableGuid,\r
133                     &BootOrderListSize\r
134                     );\r
135 \r
136   //\r
137   // If exists, delete it to hold new BootOrder\r
138   //\r
139   if (BootOrderList) {\r
140     EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
141     SafeFreePool (BootOrderList);\r
142     BootOrderList = NULL;\r
143   }\r
144   //\r
145   // Maybe here should be some check method to ensure that\r
146   // no new added boot options will be added\r
147   // but the setup engine now will give only one callback\r
148   // that is to say, user are granted only one chance to\r
149   // decide whether the boot option will be added or not\r
150   // there should be no indictor to show whether this\r
151   // is a "new" boot option\r
152   //\r
153   BootOrderListSize = BootOptionMenu.MenuNumber;\r
154 \r
155   if (BootOrderListSize > 0) {\r
156     BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16));\r
157     ASSERT (BootOrderList != NULL);\r
158     BootOrderListPtr = BootOrderList;\r
159 \r
160     //\r
161     // Get all current used Boot#### from BootOptionMenu.\r
162     // OptionNumber in each BM_LOAD_OPTION is really its\r
163     // #### value.\r
164     //\r
165     for (Index = 0; Index < BootOrderListSize; Index++) {\r
166       NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
167       *BootOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
168       BootOrderList++;\r
169     }\r
170 \r
171     BootOrderList = BootOrderListPtr;\r
172 \r
173     //\r
174     // After building the BootOrderList, write it back\r
175     //\r
176     Status = gRT->SetVariable (\r
177                     L"BootOrder",\r
178                     &gEfiGlobalVariableGuid,\r
179                     VAR_FLAG,\r
180                     BootOrderListSize * sizeof (UINT16),\r
181                     BootOrderList\r
182                     );\r
183     if (EFI_ERROR (Status)) {\r
184       return Status;\r
185     }\r
186   }\r
187   return EFI_SUCCESS;\r
188 }\r
189 \r
190 EFI_STATUS\r
191 Var_DelDriverOption (\r
192   VOID\r
193   )\r
194 /*++\r
195 \r
196 Routine Description:\r
197   Delete Load Option that represent a Deleted state in BootOptionMenu.\r
198   After deleting this Driver option, call Var_ChangeDriverOrder to\r
199   make sure DriverOrder is in valid state.\r
200   \r
201 Arguments:\r
202   LoadOption -- Pointer to the Driver option that to be deleted\r
203 \r
204 Returns:\r
205   EFI_SUCCESS\r
206   Others\r
207   \r
208 --*/\r
209 {\r
210   BM_MENU_ENTRY   *NewMenuEntry;\r
211   BM_LOAD_CONTEXT *NewLoadContext;\r
212 \r
213   UINT16          DriverString[12];\r
214   EFI_STATUS      Status;\r
215   UINTN           Index;\r
216   UINTN           Index2;\r
217 \r
218   Status  = EFI_SUCCESS;\r
219   Index2  = 0;\r
220   for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
221     NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2));\r
222     if (NULL == NewMenuEntry) {\r
223       return EFI_NOT_FOUND;\r
224     }\r
225 \r
226     NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
227     if (!NewLoadContext->Deleted) {\r
228       continue;\r
229     }\r
230 \r
231     UnicodeSPrint (\r
232       DriverString,\r
233       sizeof (DriverString),\r
234       L"Driver%04x",\r
235       NewMenuEntry->OptionNumber\r
236       );\r
237 \r
238     EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid);\r
239     Index2++;\r
240 \r
241     RemoveEntryList (&NewMenuEntry->Link);\r
242     BOpt_DestroyMenuEntry (NewMenuEntry);\r
243     NewMenuEntry = NULL;\r
244   }\r
245 \r
246   DriverOptionMenu.MenuNumber -= Index2;\r
247 \r
248   Status = Var_ChangeDriverOrder ();\r
249   return Status;\r
250 }\r
251 \r
252 EFI_STATUS\r
253 Var_ChangeDriverOrder (\r
254   VOID\r
255   )\r
256 /*++\r
257 \r
258 Routine Description:\r
259   After any operation on Driver####, there will be a discrepancy in \r
260   DriverOrder. Since some are missing but in DriverOrder, while some \r
261   are present but are not reflected by DriverOrder. Then a function \r
262   rebuild DriverOrder from scratch by content from DriverOptionMenu is \r
263   needed.\r
264   \r
265 Arguments:\r
266 \r
267 Returns:\r
268   EFI_SUCCESS\r
269   Others\r
270   \r
271 --*/\r
272 {\r
273   EFI_STATUS    Status;\r
274   BM_MENU_ENTRY *NewMenuEntry;\r
275   UINT16        *DriverOrderList;\r
276   UINT16        *DriverOrderListPtr;\r
277   UINTN         DriverOrderListSize;\r
278   UINTN         Index;\r
279 \r
280   DriverOrderList     = NULL;\r
281   DriverOrderListSize = 0;\r
282 \r
283   //\r
284   // First check whether DriverOrder is present in current configuration\r
285   //\r
286   DriverOrderList = BdsLibGetVariableAndSize (\r
287                       L"DriverOrder",\r
288                       &gEfiGlobalVariableGuid,\r
289                       &DriverOrderListSize\r
290                       );\r
291 \r
292   //\r
293   // If exists, delete it to hold new DriverOrder\r
294   //\r
295   if (DriverOrderList) {\r
296     EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
297     SafeFreePool (DriverOrderList);\r
298     DriverOrderList = NULL;\r
299   }\r
300 \r
301   DriverOrderListSize = DriverOptionMenu.MenuNumber;\r
302 \r
303   if (DriverOrderListSize > 0) {\r
304     DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16));\r
305     ASSERT (DriverOrderList != NULL);\r
306     DriverOrderListPtr = DriverOrderList;\r
307 \r
308     //\r
309     // Get all current used Driver#### from DriverOptionMenu.\r
310     // OptionNumber in each BM_LOAD_OPTION is really its\r
311     // #### value.\r
312     //\r
313     for (Index = 0; Index < DriverOrderListSize; Index++) {\r
314       NewMenuEntry      = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
315       *DriverOrderList  = (UINT16) NewMenuEntry->OptionNumber;\r
316       DriverOrderList++;\r
317     }\r
318 \r
319     DriverOrderList = DriverOrderListPtr;\r
320 \r
321     //\r
322     // After building the DriverOrderList, write it back\r
323     //\r
324     Status = gRT->SetVariable (\r
325                     L"DriverOrder",\r
326                     &gEfiGlobalVariableGuid,\r
327                     VAR_FLAG,\r
328                     DriverOrderListSize * sizeof (UINT16),\r
329                     DriverOrderList\r
330                     );\r
331     if (EFI_ERROR (Status)) {\r
332       return Status;\r
333     }\r
334   }\r
335   return EFI_SUCCESS;\r
336 }\r
337 \r
338 VOID\r
339 Var_UpdateAllConsoleOption (\r
340   VOID\r
341   )\r
342 {\r
343   EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;\r
344   EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;\r
345   EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;\r
346   EFI_STATUS                Status;\r
347 \r
348   OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);\r
349   InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);\r
350   ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);\r
351   if (OutDevicePath) {\r
352     ChangeVariableDevicePath (OutDevicePath);\r
353     Status = gRT->SetVariable (\r
354                     L"ConOut",\r
355                     &gEfiGlobalVariableGuid,\r
356                     VAR_FLAG,\r
357                     GetDevicePathSize (OutDevicePath),\r
358                     OutDevicePath\r
359                     );\r
360     ASSERT (!EFI_ERROR (Status));\r
361   }\r
362 \r
363   if (InpDevicePath) {\r
364     ChangeVariableDevicePath (InpDevicePath);\r
365     Status = gRT->SetVariable (\r
366                     L"ConIn",\r
367                     &gEfiGlobalVariableGuid,\r
368                     VAR_FLAG,\r
369                     GetDevicePathSize (InpDevicePath),\r
370                     InpDevicePath\r
371                     );\r
372     ASSERT (!EFI_ERROR (Status));\r
373   }\r
374 \r
375   if (ErrDevicePath) {\r
376     ChangeVariableDevicePath (ErrDevicePath);\r
377     Status = gRT->SetVariable (\r
378                     L"ErrOut",\r
379                     &gEfiGlobalVariableGuid,\r
380                     VAR_FLAG,\r
381                     GetDevicePathSize (ErrDevicePath),\r
382                     ErrDevicePath\r
383                     );\r
384     ASSERT (!EFI_ERROR (Status));\r
385   }\r
386 }\r
387 \r
388 EFI_STATUS\r
389 Var_UpdateConsoleOption (\r
390   IN UINT16                     *ConsoleName,\r
391   IN BM_MENU_OPTION             *ConsoleMenu,\r
392   IN UINT16                     UpdatePageId\r
393   )\r
394 {\r
395   EFI_DEVICE_PATH_PROTOCOL  *ConDevicePath;\r
396   BM_MENU_ENTRY             *NewMenuEntry;\r
397   BM_CONSOLE_CONTEXT        *NewConsoleContext;\r
398   BM_TERMINAL_CONTEXT       *NewTerminalContext;\r
399   EFI_STATUS                Status;\r
400   VENDOR_DEVICE_PATH        Vendor;\r
401   EFI_DEVICE_PATH_PROTOCOL  *TerminalDevicePath;\r
402   UINTN                     Index;\r
403   UINT16                    *Temp;\r
404 \r
405   ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
406   if (ConDevicePath != NULL) {\r
407     EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid);\r
408     SafeFreePool (ConDevicePath);\r
409     ConDevicePath = NULL;\r
410   };\r
411 \r
412   //\r
413   // First add all console input device to it from console input menu\r
414   //\r
415   for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) {\r
416     NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);\r
417     if (NULL == NewMenuEntry) {\r
418       return EFI_NOT_FOUND;\r
419     }\r
420 \r
421     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
422     if (NewConsoleContext->IsActive) {\r
423       ConDevicePath = AppendDevicePathInstance (\r
424                         ConDevicePath,\r
425                         NewConsoleContext->DevicePath\r
426                         );\r
427     }\r
428   }\r
429 \r
430   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
431     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
432     if (NULL == NewMenuEntry) {\r
433       return EFI_NOT_FOUND;\r
434     }\r
435 \r
436     NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
437     if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) ||\r
438         (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) ||\r
439         (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID))\r
440         ) {\r
441       Vendor.Header.Type    = MESSAGING_DEVICE_PATH;\r
442       Vendor.Header.SubType = MSG_VENDOR_DP;\r
443       CopyMem (\r
444         &Vendor.Guid,\r
445         &Guid[NewTerminalContext->TerminalType],\r
446         sizeof (EFI_GUID)\r
447         );\r
448       SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));\r
449       TerminalDevicePath = AppendDevicePathNode (\r
450                             NewTerminalContext->DevicePath,\r
451                             (EFI_DEVICE_PATH_PROTOCOL *) &Vendor\r
452                             );\r
453       ASSERT (TerminalDevicePath != NULL);\r
454       ChangeTerminalDevicePath (TerminalDevicePath, TRUE);\r
455       Temp = DevicePathToStr (TerminalDevicePath);\r
456       ConDevicePath = AppendDevicePathInstance (\r
457                         ConDevicePath,\r
458                         TerminalDevicePath\r
459                         );\r
460     }\r
461   }\r
462 \r
463   if (ConDevicePath) {\r
464     Status = gRT->SetVariable (\r
465                     ConsoleName,\r
466                     &gEfiGlobalVariableGuid,\r
467                     VAR_FLAG,\r
468                     GetDevicePathSize (ConDevicePath),\r
469                     ConDevicePath\r
470                     );\r
471     if (EFI_ERROR (Status)) {\r
472       return Status;\r
473     }\r
474   }\r
475 \r
476   return EFI_SUCCESS;\r
477 \r
478 }\r
479 \r
480 EFI_STATUS\r
481 Var_UpdateConsoleInpOption (\r
482   VOID\r
483   )\r
484 {\r
485   return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID);\r
486 }\r
487 \r
488 EFI_STATUS\r
489 Var_UpdateConsoleOutOption (\r
490   VOID\r
491   )\r
492 {\r
493   return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID);\r
494 }\r
495 \r
496 EFI_STATUS\r
497 Var_UpdateErrorOutOption (\r
498   VOID\r
499   )\r
500 {\r
501   return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID);\r
502 }\r
503 \r
504 EFI_STATUS\r
505 Var_UpdateDriverOption (\r
506   IN  BMM_CALLBACK_DATA         *CallbackData,\r
507   IN  EFI_HII_HANDLE            HiiHandle,\r
508   IN  UINT16                    *DescriptionData,\r
509   IN  UINT16                    *OptionalData,\r
510   IN  UINT8                     ForceReconnect\r
511   )\r
512 {\r
513   UINT16          Index;\r
514   UINT16          *DriverOrderList;\r
515   UINT16          *NewDriverOrderList;\r
516   UINT16          DriverString[12];\r
517   UINTN           DriverOrderListSize;\r
518   VOID            *Buffer;\r
519   UINTN           BufferSize;\r
520   UINT8           *Ptr;\r
521   BM_MENU_ENTRY   *NewMenuEntry;\r
522   BM_LOAD_CONTEXT *NewLoadContext;\r
523   BOOLEAN         OptionalDataExist;\r
524   EFI_STATUS      Status;\r
525 \r
526   OptionalDataExist = FALSE;\r
527 \r
528   Index             = BOpt_GetDriverOptionNumber ();\r
529   UnicodeSPrint (\r
530     DriverString,\r
531     sizeof (DriverString),\r
532     L"Driver%04x",\r
533     Index\r
534     );\r
535 \r
536   if (*DescriptionData == 0x0000) {\r
537     StrCpy (DescriptionData, DriverString);\r
538   }\r
539 \r
540   BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
541 \r
542   if (*OptionalData != 0x0000) {\r
543     OptionalDataExist = TRUE;\r
544     BufferSize += StrSize (OptionalData);\r
545   }\r
546 \r
547   Buffer = AllocateZeroPool (BufferSize);\r
548   if (NULL == Buffer) {\r
549     return EFI_OUT_OF_RESOURCES;\r
550   }\r
551 \r
552   NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
553   if (NULL == NewMenuEntry) {\r
554     return EFI_OUT_OF_RESOURCES;\r
555   }\r
556 \r
557   NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
558   NewLoadContext->Deleted         = FALSE;\r
559   NewLoadContext->LoadOptionSize  = BufferSize;\r
560   Ptr = (UINT8 *) Buffer;\r
561   NewLoadContext->LoadOption = Ptr;\r
562   *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1);\r
563   NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
564   NewLoadContext->IsActive = TRUE;\r
565   NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
566 \r
567   Ptr += sizeof (UINT32);\r
568   *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
569   NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
570 \r
571   Ptr += sizeof (UINT16);\r
572   CopyMem (\r
573     Ptr,\r
574     DescriptionData,\r
575     StrSize (DescriptionData)\r
576     );\r
577 \r
578   NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData));\r
579   ASSERT (NewLoadContext->Description != NULL);\r
580   NewMenuEntry->DisplayString = NewLoadContext->Description;\r
581   CopyMem (\r
582     NewLoadContext->Description,\r
583     (VOID *) Ptr,\r
584     StrSize (DescriptionData)\r
585     );\r
586 \r
587   Ptr += StrSize (DescriptionData);\r
588   CopyMem (\r
589     Ptr,\r
590     CallbackData->LoadContext->FilePathList,\r
591     GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
592     );\r
593 \r
594   NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
595   ASSERT (NewLoadContext->FilePathList != NULL);\r
596 \r
597   CopyMem (\r
598     NewLoadContext->FilePathList,\r
599     (VOID *) Ptr,\r
600     GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
601     );\r
602 \r
603   NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
604   NewMenuEntry->OptionNumber  = Index;\r
605   NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
606                                       CallbackData,\r
607                                       DriverOptionStrDepository\r
608                                       );\r
609   CallbackData->Hii->NewString (\r
610                       CallbackData->Hii,\r
611                       NULL,\r
612                       HiiHandle,\r
613                       &NewMenuEntry->DisplayStringToken,\r
614                       NewMenuEntry->DisplayString\r
615                       );\r
616 \r
617   NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
618                                     CallbackData,\r
619                                     DriverOptionHelpStrDepository\r
620                                     );\r
621   CallbackData->Hii->NewString (\r
622                       CallbackData->Hii,\r
623                       NULL,\r
624                       HiiHandle,\r
625                       &NewMenuEntry->HelpStringToken,\r
626                       NewMenuEntry->HelpString\r
627                       );\r
628 \r
629   if (OptionalDataExist) {\r
630     Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
631 \r
632     CopyMem (\r
633       Ptr,\r
634       OptionalData,\r
635       StrSize (OptionalData)\r
636       );\r
637   }\r
638 \r
639   Status = gRT->SetVariable (\r
640                   DriverString,\r
641                   &gEfiGlobalVariableGuid,\r
642                   VAR_FLAG,\r
643                   BufferSize,\r
644                   Buffer\r
645                   );\r
646   DriverOrderList = BdsLibGetVariableAndSize (\r
647                       L"DriverOrder",\r
648                       &gEfiGlobalVariableGuid,\r
649                       &DriverOrderListSize\r
650                       );\r
651   NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16));\r
652   ASSERT (NewDriverOrderList != NULL);\r
653   CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize);\r
654   NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index;\r
655   if (DriverOrderList != NULL) {\r
656     EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
657   }\r
658 \r
659   Status = gRT->SetVariable (\r
660                   L"DriverOrder",\r
661                   &gEfiGlobalVariableGuid,\r
662                   VAR_FLAG,\r
663                   DriverOrderListSize + sizeof (UINT16),\r
664                   NewDriverOrderList\r
665                   );\r
666   SafeFreePool (DriverOrderList);\r
667   DriverOrderList = NULL;\r
668   SafeFreePool (NewDriverOrderList);\r
669   NewDriverOrderList = NULL;\r
670   InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
671   DriverOptionMenu.MenuNumber++;\r
672 \r
673   *DescriptionData  = 0x0000;\r
674   *OptionalData     = 0x0000;\r
675   return EFI_SUCCESS;\r
676 }\r
677 \r
678 EFI_STATUS\r
679 Var_UpdateBootOption (\r
680   IN  BMM_CALLBACK_DATA                   *CallbackData,\r
681   IN  FILE_EXPLORER_NV_DATA               *NvRamMap\r
682   )\r
683 {\r
684   UINT16          *BootOrderList;\r
685   UINT16          *NewBootOrderList;\r
686   UINTN           BootOrderListSize;\r
687   UINT16          BootString[10];\r
688   VOID            *Buffer;\r
689   UINTN           BufferSize;\r
690   UINT8           *Ptr;\r
691   UINT16          Index;\r
692   BM_MENU_ENTRY   *NewMenuEntry;\r
693   BM_LOAD_CONTEXT *NewLoadContext;\r
694   BOOLEAN         OptionalDataExist;\r
695   EFI_STATUS      Status;\r
696 \r
697   OptionalDataExist = FALSE;\r
698 \r
699   Index             = BOpt_GetBootOptionNumber ();\r
700   UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index);\r
701 \r
702   if (NvRamMap->DescriptionData[0] == 0x0000) {\r
703     StrCpy (NvRamMap->DescriptionData, BootString);\r
704   }\r
705 \r
706   BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
707 \r
708   if (NvRamMap->OptionalData[0] != 0x0000) {\r
709     OptionalDataExist = TRUE;\r
710     BufferSize += StrSize (NvRamMap->OptionalData);\r
711   }\r
712 \r
713   Buffer = AllocateZeroPool (BufferSize);\r
714   if (NULL == Buffer) {\r
715     return EFI_OUT_OF_RESOURCES;\r
716   }\r
717 \r
718   NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
719   if (NULL == NewMenuEntry) {\r
720     return EFI_OUT_OF_RESOURCES;\r
721   }\r
722 \r
723   NewLoadContext                  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
724   NewLoadContext->Deleted         = FALSE;\r
725   NewLoadContext->LoadOptionSize  = BufferSize;\r
726   Ptr = (UINT8 *) Buffer;\r
727   NewLoadContext->LoadOption = Ptr;\r
728   *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE;\r
729   NewLoadContext->Attributes = *((UINT32 *) Ptr);\r
730   NewLoadContext->IsActive = TRUE;\r
731   NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
732 \r
733   Ptr += sizeof (UINT32);\r
734   *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
735   NewLoadContext->FilePathListLength = *((UINT16 *) Ptr);\r
736   Ptr += sizeof (UINT16);\r
737 \r
738   CopyMem (\r
739     Ptr,\r
740     NvRamMap->DescriptionData,\r
741     StrSize (NvRamMap->DescriptionData)\r
742     );\r
743 \r
744   NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData));\r
745   ASSERT (NewLoadContext->Description != NULL);\r
746 \r
747   NewMenuEntry->DisplayString = NewLoadContext->Description;\r
748   CopyMem (\r
749     NewLoadContext->Description,\r
750     (VOID *) Ptr,\r
751     StrSize (NvRamMap->DescriptionData)\r
752     );\r
753 \r
754   Ptr += StrSize (NvRamMap->DescriptionData);\r
755   CopyMem (\r
756     Ptr,\r
757     CallbackData->LoadContext->FilePathList,\r
758     GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
759     );\r
760 \r
761   NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList));\r
762   ASSERT (NewLoadContext->FilePathList != NULL);\r
763 \r
764   CopyMem (\r
765     NewLoadContext->FilePathList,\r
766     (VOID *) Ptr,\r
767     GetDevicePathSize (CallbackData->LoadContext->FilePathList)\r
768     );\r
769 \r
770   NewMenuEntry->HelpString    = DevicePathToStr (NewLoadContext->FilePathList);\r
771   NewMenuEntry->OptionNumber  = Index;\r
772   NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
773                                       CallbackData,\r
774                                       BootOptionStrDepository\r
775                                       );\r
776   CallbackData->Hii->NewString (\r
777                       CallbackData->Hii,\r
778                       NULL,\r
779                       CallbackData->FeHiiHandle,\r
780                       &NewMenuEntry->DisplayStringToken,\r
781                       NewMenuEntry->DisplayString\r
782                       );\r
783 \r
784   NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
785                                     CallbackData,\r
786                                     BootOptionHelpStrDepository\r
787                                     );\r
788 \r
789   CallbackData->Hii->NewString (\r
790                       CallbackData->Hii,\r
791                       NULL,\r
792                       CallbackData->FeHiiHandle,\r
793                       &NewMenuEntry->HelpStringToken,\r
794                       NewMenuEntry->HelpString\r
795                       );\r
796 \r
797   if (OptionalDataExist) {\r
798     Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList);\r
799 \r
800     CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData));\r
801   }\r
802 \r
803   Status = gRT->SetVariable (\r
804                   BootString,\r
805                   &gEfiGlobalVariableGuid,\r
806                   VAR_FLAG,\r
807                   BufferSize,\r
808                   Buffer\r
809                   );\r
810 \r
811   BootOrderList = BdsLibGetVariableAndSize (\r
812                     L"BootOrder",\r
813                     &gEfiGlobalVariableGuid,\r
814                     &BootOrderListSize\r
815                     );\r
816 \r
817   NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16));\r
818   ASSERT (NewBootOrderList != NULL);\r
819   CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize);\r
820   NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index;\r
821 \r
822   if (BootOrderList != NULL) {\r
823     EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
824   }\r
825 \r
826   Status = gRT->SetVariable (\r
827                   L"BootOrder",\r
828                   &gEfiGlobalVariableGuid,\r
829                   VAR_FLAG,\r
830                   BootOrderListSize + sizeof (UINT16),\r
831                   NewBootOrderList\r
832                   );\r
833 \r
834   SafeFreePool (BootOrderList);\r
835   BootOrderList = NULL;\r
836   SafeFreePool (NewBootOrderList);\r
837   NewBootOrderList = NULL;\r
838   InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
839   BootOptionMenu.MenuNumber++;\r
840 \r
841   NvRamMap->DescriptionData[0]  = 0x0000;\r
842   NvRamMap->OptionalData[0]     = 0x0000;\r
843   return EFI_SUCCESS;\r
844 }\r
845 \r
846 EFI_STATUS\r
847 Var_UpdateBootNext (\r
848   IN BMM_CALLBACK_DATA            *CallbackData\r
849   )\r
850 {\r
851   BM_MENU_ENTRY     *NewMenuEntry;\r
852   BM_LOAD_CONTEXT   *NewLoadContext;\r
853   BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
854   UINT16            Index;\r
855   EFI_STATUS        Status;\r
856 \r
857   Status            = EFI_SUCCESS;\r
858   CurrentFakeNVMap  = CallbackData->BmmFakeNvData;\r
859   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
860     NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
861     if (NULL == NewMenuEntry) {\r
862       return EFI_NOT_FOUND;\r
863     }\r
864 \r
865     NewLoadContext              = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
866     NewLoadContext->IsBootNext  = FALSE;\r
867   }\r
868 \r
869   if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) {\r
870     EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid);\r
871     return EFI_SUCCESS;\r
872   }\r
873 \r
874   NewMenuEntry = BOpt_GetMenuEntry (\r
875                   &BootOptionMenu,\r
876                   CurrentFakeNVMap->BootNext\r
877                   );\r
878   if (NULL == NewMenuEntry) {\r
879     return EFI_NOT_FOUND;\r
880   }\r
881 \r
882   NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
883   Status = gRT->SetVariable (\r
884                   L"BootNext",\r
885                   &gEfiGlobalVariableGuid,\r
886                   VAR_FLAG,\r
887                   sizeof (UINT16),\r
888                   &NewMenuEntry->OptionNumber\r
889                   );\r
890   NewLoadContext->IsBootNext              = TRUE;\r
891   CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext;\r
892   return Status;\r
893 }\r
894 \r
895 EFI_STATUS\r
896 Var_UpdateBootOrder (\r
897   IN BMM_CALLBACK_DATA            *CallbackData\r
898   )\r
899 {\r
900   EFI_STATUS  Status;\r
901   UINT16      Index;\r
902   UINT16      *BootOrderList;\r
903   UINT16      *NewBootOrderList;\r
904   UINTN       BootOrderListSize;\r
905   UINT8       *Map;\r
906 \r
907   BootOrderList     = NULL;\r
908   BootOrderListSize = 0;\r
909 \r
910   //\r
911   // First check whether BootOrder is present in current configuration\r
912   //\r
913   BootOrderList = BdsLibGetVariableAndSize (\r
914                     L"BootOrder",\r
915                     &gEfiGlobalVariableGuid,\r
916                     &BootOrderListSize\r
917                     );\r
918 \r
919   NewBootOrderList = AllocateZeroPool (BootOrderListSize);\r
920   if (!NewBootOrderList) {\r
921     return EFI_OUT_OF_RESOURCES;\r
922   }\r
923 \r
924   Map = AllocateZeroPool (BootOrderListSize / sizeof (UINT16));\r
925   if (!Map) {\r
926     return EFI_OUT_OF_RESOURCES;\r
927   }\r
928   //\r
929   // If exists, delete it to hold new BootOrder\r
930   //\r
931   if (BootOrderList) {\r
932     EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid);\r
933   }\r
934 \r
935   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
936     NewBootOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;\r
937   }\r
938 \r
939   Status = gRT->SetVariable (\r
940                   L"BootOrder",\r
941                   &gEfiGlobalVariableGuid,\r
942                   VAR_FLAG,\r
943                   BootOrderListSize,\r
944                   NewBootOrderList\r
945                   );\r
946   SafeFreePool (BootOrderList);\r
947   SafeFreePool (NewBootOrderList);\r
948   SafeFreePool (Map);\r
949   if (EFI_ERROR (Status)) {\r
950     return Status;\r
951   }\r
952 \r
953   BOpt_FreeMenu (&BootOptionMenu);\r
954   BOpt_GetBootOptions (CallbackData);\r
955 \r
956   return EFI_SUCCESS;\r
957 \r
958 }\r
959 \r
960 EFI_STATUS\r
961 Var_UpdateDriverOrder (\r
962   IN BMM_CALLBACK_DATA            *CallbackData\r
963   )\r
964 {\r
965   EFI_STATUS  Status;\r
966   UINT16      Index;\r
967   UINT16      *DriverOrderList;\r
968   UINT16      *NewDriverOrderList;\r
969   UINTN       DriverOrderListSize;\r
970 \r
971   DriverOrderList     = NULL;\r
972   DriverOrderListSize = 0;\r
973 \r
974   //\r
975   // First check whether DriverOrder is present in current configuration\r
976   //\r
977   DriverOrderList = BdsLibGetVariableAndSize (\r
978                       L"DriverOrder",\r
979                       &gEfiGlobalVariableGuid,\r
980                       &DriverOrderListSize\r
981                       );\r
982 \r
983   NewDriverOrderList = AllocateZeroPool (DriverOrderListSize);\r
984 \r
985   if (!NewDriverOrderList) {\r
986     return EFI_OUT_OF_RESOURCES;\r
987   }\r
988   //\r
989   // If exists, delete it to hold new DriverOrder\r
990   //\r
991   if (DriverOrderList) {\r
992     EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid);\r
993   }\r
994 \r
995   for (Index = 0; Index < DriverOrderListSize; Index++) {\r
996     NewDriverOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1;\r
997   }\r
998 \r
999   Status = gRT->SetVariable (\r
1000                   L"DriverOrder",\r
1001                   &gEfiGlobalVariableGuid,\r
1002                   VAR_FLAG,\r
1003                   DriverOrderListSize,\r
1004                   NewDriverOrderList\r
1005                   );\r
1006   if (EFI_ERROR (Status)) {\r
1007     return Status;\r
1008   }\r
1009 \r
1010   SafeFreePool (DriverOrderList);\r
1011 \r
1012   BOpt_FreeMenu (&DriverOptionMenu);\r
1013   BOpt_GetDriverOptions (CallbackData);\r
1014   return EFI_SUCCESS;\r
1015 }\r
1016 \r
1017 EFI_STATUS\r
1018 Var_UpdateBBSOption (\r
1019   IN BMM_CALLBACK_DATA            *CallbackData\r
1020   )\r
1021 {\r
1022   UINTN                       Index;\r
1023   UINTN                       Index2;\r
1024   VOID                        *BootOptionVar;\r
1025   CHAR16                      VarName[100];\r
1026   UINTN                       OptionSize;\r
1027   UINT16                      FilePathSize;\r
1028   UINT8                       *Ptr;\r
1029   EFI_STATUS                  Status;\r
1030   CHAR16                      DescString[100];\r
1031   UINTN                       NewOptionSize;\r
1032   UINT8                       *NewOptionPtr;\r
1033   UINT8                       *TempPtr;\r
1034   UINT32                      *Attribute;\r
1035 \r
1036   BM_MENU_OPTION              *OptionMenu;\r
1037   BM_LEGACY_DEVICE_CONTEXT    *LegacyDeviceContext;\r
1038   UINT8                       *LegacyDev;\r
1039   UINT8                       *VarData;\r
1040   UINTN                       VarSize;\r
1041   BM_MENU_ENTRY               *NewMenuEntry;\r
1042   BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder;\r
1043   UINT8                       *OriginalPtr;\r
1044   UINT8                       *DisMap;\r
1045   UINTN                       Pos;\r
1046   UINTN                       Bit;\r
1047   UINT16                      *NewOrder;\r
1048   UINT16                      Tmp;\r
1049 \r
1050   LegacyDeviceContext = NULL;\r
1051   DisMap              = NULL;\r
1052   NewOrder            = NULL;\r
1053 \r
1054   if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1055     OptionMenu            = (BM_MENU_OPTION *) &LegacyFDMenu;\r
1056     LegacyDev             = CallbackData->BmmFakeNvData->LegacyFD;\r
1057     CallbackData->BbsType = BBS_FLOPPY;\r
1058   } else {\r
1059     if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1060       OptionMenu            = (BM_MENU_OPTION *) &LegacyHDMenu;\r
1061       LegacyDev             = CallbackData->BmmFakeNvData->LegacyHD;\r
1062       CallbackData->BbsType = BBS_HARDDISK;\r
1063     } else {\r
1064       if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1065         OptionMenu            = (BM_MENU_OPTION *) &LegacyCDMenu;\r
1066         LegacyDev             = CallbackData->BmmFakeNvData->LegacyCD;\r
1067         CallbackData->BbsType = BBS_CDROM;\r
1068       } else {\r
1069         if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) {\r
1070           OptionMenu            = (BM_MENU_OPTION *) &LegacyNETMenu;\r
1071           LegacyDev             = CallbackData->BmmFakeNvData->LegacyNET;\r
1072           CallbackData->BbsType = BBS_EMBED_NETWORK;\r
1073         } else {\r
1074           OptionMenu            = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
1075           LegacyDev             = CallbackData->BmmFakeNvData->LegacyBEV;\r
1076           CallbackData->BbsType = BBS_BEV_DEVICE;\r
1077         }\r
1078       }\r
1079     }\r
1080   }\r
1081 \r
1082   DisMap  = CallbackData->BmmOldFakeNVData.DisableMap;\r
1083   Status  = EFI_SUCCESS;\r
1084 \r
1085   //\r
1086   // Find the first device's context\r
1087   // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext\r
1088   // because we just use it to fill the desc string, and user can not see the string in UI\r
1089   //\r
1090   for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1091     NewMenuEntry        = BOpt_GetMenuEntry (OptionMenu, Index);\r
1092     LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
1093     if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) {\r
1094       DEBUG ((EFI_D_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description));\r
1095       break;\r
1096     }\r
1097   }\r
1098   //\r
1099   // Update the Variable "LegacyDevOrder"\r
1100   //\r
1101   VarData = (UINT8 *) BdsLibGetVariableAndSize (\r
1102                         VarLegacyDevOrder,\r
1103                         &EfiLegacyDevOrderGuid,\r
1104                         &VarSize\r
1105                         );\r
1106 \r
1107   if (NULL == VarData) {\r
1108     return EFI_NOT_FOUND;\r
1109   }\r
1110 \r
1111   OriginalPtr = VarData;\r
1112   DevOrder    = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
1113 \r
1114   while (VarData < VarData + VarSize) {\r
1115     if (DevOrder->BbsType == CallbackData->BbsType) {\r
1116       break;\r
1117     }\r
1118 \r
1119     VarData += sizeof (BBS_TYPE);\r
1120     VarData += *(UINT16 *) VarData;\r
1121     DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData;\r
1122   }\r
1123 \r
1124   if (VarData >= VarData + VarSize) {\r
1125     SafeFreePool (OriginalPtr);\r
1126     return EFI_NOT_FOUND;\r
1127   }\r
1128 \r
1129   NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16));\r
1130   if (NULL == NewOrder) {\r
1131     SafeFreePool (VarData);\r
1132     return EFI_OUT_OF_RESOURCES;\r
1133   }\r
1134 \r
1135   for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {\r
1136     if (0xFF == LegacyDev[Index]) {\r
1137       break;\r
1138     }\r
1139 \r
1140     NewOrder[Index] = LegacyDev[Index];\r
1141   }\r
1142   //\r
1143   // Only the enable/disable state of each boot device with same device type can be changed,\r
1144   // so we can count on the index information in DevOrder.\r
1145   // DisMap bit array is the only reliable source to check a device's en/dis state,\r
1146   // so we use DisMap to set en/dis state of each item in NewOrder array\r
1147   //\r
1148   for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) {\r
1149     Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16));\r
1150     Tmp &= 0xFF;\r
1151     Pos = Tmp / 8;\r
1152     Bit = 7 - (Tmp % 8);\r
1153     if (DisMap[Pos] & (1 << Bit)) {\r
1154       NewOrder[Index] = (UINT16) (0xFF00 | Tmp);\r
1155       Index++;\r
1156     }\r
1157   }\r
1158 \r
1159   CopyMem (\r
1160     (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16),\r
1161     NewOrder,\r
1162     DevOrder->Length - sizeof (UINT16)\r
1163     );\r
1164   SafeFreePool (NewOrder);\r
1165 \r
1166   Status = gRT->SetVariable (\r
1167                   VarLegacyDevOrder,\r
1168                   &EfiLegacyDevOrderGuid,\r
1169                   VAR_FLAG,\r
1170                   VarSize,\r
1171                   OriginalPtr\r
1172                   );\r
1173 \r
1174   SafeFreePool (OriginalPtr);\r
1175 \r
1176   //\r
1177   // Update Optional Data of Boot####\r
1178   //\r
1179   BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize);\r
1180 \r
1181   if (NULL != BootOptionVar) {\r
1182     CopyMem (\r
1183       DescString,\r
1184       LegacyDeviceContext->Description,\r
1185       StrSize (LegacyDeviceContext->Description)\r
1186       );\r
1187 \r
1188     NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) + sizeof (BBS_TABLE) + sizeof (UINT16);\r
1189 \r
1190     UnicodeSPrint (VarName, 100, L"Boot%04x", Index);\r
1191 \r
1192     Ptr       = BootOptionVar;\r
1193 \r
1194     Attribute = (UINT32 *) Ptr;\r
1195     *Attribute |= LOAD_OPTION_ACTIVE;\r
1196     if (0xFF == LegacyDev[0]) {\r
1197       //\r
1198       // Disable this legacy boot option\r
1199       //\r
1200       *Attribute &= ~LOAD_OPTION_ACTIVE;\r
1201     }\r
1202 \r
1203     Ptr += sizeof (UINT32);\r
1204 \r
1205     FilePathSize = *(UINT16 *) Ptr;\r
1206     Ptr += sizeof (UINT16);\r
1207 \r
1208     NewOptionSize += FilePathSize;\r
1209 \r
1210     NewOptionPtr = AllocateZeroPool (NewOptionSize);\r
1211     if (NULL == NewOptionPtr) {\r
1212       return EFI_OUT_OF_RESOURCES;\r
1213     }\r
1214 \r
1215     TempPtr = NewOptionPtr;\r
1216 \r
1217     //\r
1218     // Copy previous option data to new option except the description string\r
1219     //\r
1220     CopyMem (\r
1221       TempPtr,\r
1222       BootOptionVar,\r
1223       sizeof (UINT32) + sizeof (UINT16)\r
1224       );\r
1225 \r
1226     TempPtr += (sizeof (UINT32) + sizeof (UINT16));\r
1227 \r
1228     CopyMem (\r
1229       TempPtr,\r
1230       DescString,\r
1231       StrSize (DescString)\r
1232       );\r
1233 \r
1234     TempPtr += StrSize (DescString);\r
1235 \r
1236     //\r
1237     // Description = (CHAR16 *)Ptr;\r
1238     //\r
1239     Ptr += StrSize ((CHAR16 *) Ptr);\r
1240 \r
1241     CopyMem (\r
1242       TempPtr,\r
1243       Ptr,\r
1244       FilePathSize\r
1245       );\r
1246 \r
1247     TempPtr += FilePathSize;\r
1248 \r
1249     //\r
1250     // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr;\r
1251     //\r
1252     Ptr += FilePathSize;\r
1253 \r
1254     //\r
1255     // Now Ptr point to optional data, i.e. Bbs Table\r
1256     //\r
1257     CopyMem (\r
1258       TempPtr,\r
1259       LegacyDeviceContext->BbsTable,\r
1260       sizeof (BBS_TABLE)\r
1261       );\r
1262 \r
1263     TempPtr += sizeof (BBS_TABLE);\r
1264     *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index;\r
1265 \r
1266     Status = gRT->SetVariable (\r
1267                     VarName,\r
1268                     &gEfiGlobalVariableGuid,\r
1269                     VAR_FLAG,\r
1270                     NewOptionSize,\r
1271                     NewOptionPtr\r
1272                     );\r
1273 \r
1274     SafeFreePool (NewOptionPtr);\r
1275     SafeFreePool (BootOptionVar);\r
1276   }\r
1277 \r
1278   BOpt_GetBootOptions (CallbackData);\r
1279   return Status;\r
1280 }\r