]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c
IntelFrameworkModulePkg: Clean up source files
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / UpdateDriverDxe / UpdateDispatcher.c
CommitLineData
b2824a8e 1/** @file\r
2 Functions in this file will mainly focus on looking through the capsule\r
3 for the image to be programmed, and the flash area that is going to be\r
4 programed.\r
5\r
0a6f4824 6 Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>\r
b2824a8e 7\r
8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions\r
10 of the BSD License which accompanies this distribution. The\r
11 full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19#include "UpdateDriver.h"\r
20\r
b2824a8e 21EFI_HII_HANDLE gHiiHandle;\r
22\r
23/**\r
24 Update the whole FV, or certain files in the FV.\r
0a6f4824 25\r
b2824a8e 26 @param ConfigData Pointer to the config data on updating file.\r
27 @param ImageBuffer Image buffer to be updated.\r
28 @param ImageSize Image size.\r
29 @param FileType FFS file type.\r
30 @param FileAttributes FFS file attribute.\r
31\r
32 @retval EFI_NOT_FOUND The matched FVB protocol is not found.\r
33 @retval EFI_SUCCESS The image buffer is updated into FV.\r
34\r
35**/\r
36EFI_STATUS\r
37PerformUpdateOnFirmwareVolume (\r
38 IN UPDATE_CONFIG_DATA *ConfigData,\r
39 IN UINT8 *ImageBuffer,\r
40 IN UINTN ImageSize,\r
41 IN EFI_FV_FILETYPE FileType,\r
42 IN EFI_FV_FILE_ATTRIBUTES FileAttributes\r
43 )\r
44{\r
45 EFI_STATUS Status;\r
46 BOOLEAN Found;\r
47 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
48 UINTN Index;\r
49 UINTN NumOfHandles;\r
50 EFI_HANDLE *HandleBuffer;\r
51 EFI_PHYSICAL_ADDRESS BaseAddress;\r
52 EFI_FVB_ATTRIBUTES_2 Attributes;\r
53\r
54 //\r
55 // Locate all Fvb protocol\r
56 //\r
57 HandleBuffer = NULL;\r
58 Status = gBS->LocateHandleBuffer (\r
59 ByProtocol,\r
60 &gEfiFirmwareVolumeBlockProtocolGuid,\r
61 NULL,\r
62 &NumOfHandles,\r
63 &HandleBuffer\r
64 );\r
65 if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {\r
66 if (HandleBuffer != NULL) {\r
67 FreePool (HandleBuffer);\r
68 }\r
69 return EFI_NOT_FOUND;\r
70 }\r
71\r
72 //\r
73 // Check the FVB protocol one by one\r
74 //\r
75 Found = FALSE;\r
76 FvbProtocol = NULL;\r
77 for (Index = 0; Index < NumOfHandles; Index++) {\r
78 Status = gBS->HandleProtocol (\r
79 HandleBuffer[Index],\r
80 &gEfiFirmwareVolumeBlockProtocolGuid,\r
81 (VOID **) &FvbProtocol\r
82 );\r
83 if (EFI_ERROR (Status)) {\r
84 break;\r
85 }\r
86\r
87 //\r
88 // Ensure this FVB protocol supported Write operation.\r
89 //\r
90 Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);\r
91 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
0a6f4824 92 continue;\r
b2824a8e 93 }\r
94\r
95 Status = FvbProtocol->GetPhysicalAddress (\r
96 FvbProtocol,\r
97 &BaseAddress\r
98 );\r
99 if (EFI_ERROR (Status)) {\r
100 break;\r
101 }\r
102 if (BaseAddress == ConfigData->BaseAddress) {\r
103 Found = TRUE;\r
104 break;\r
105 }\r
106 }\r
107\r
108 if (!Found) {\r
109 if (HandleBuffer != NULL) {\r
110 FreePool (HandleBuffer);\r
111 HandleBuffer = NULL;\r
112 }\r
113 return EFI_NOT_FOUND;\r
114 }\r
115\r
116 //\r
117 // Now we have got the corresponding FVB protocol. Use the FVB protocol\r
118 // to update the whole FV, or certain files in the FV.\r
119 //\r
120 if (ConfigData->UpdateType == UpdateWholeFV) {\r
121 if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
122 Status = EFI_INVALID_PARAMETER;\r
123 } else {\r
124 Status = PerformUpdateOnWholeFv (\r
125 HandleBuffer[Index],\r
126 FvbProtocol,\r
127 ConfigData,\r
128 ImageBuffer,\r
129 ImageSize\r
130 );\r
131 }\r
132 } else if (ConfigData->UpdateType == UpdateFvFile) {\r
133 Status = PerformUpdateOnFvFile (\r
134 HandleBuffer[Index],\r
135 FvbProtocol,\r
136 ConfigData,\r
137 ImageBuffer,\r
138 ImageSize,\r
139 FileType,\r
140 FileAttributes\r
141 );\r
142 }\r
143\r
144 if (HandleBuffer != NULL) {\r
145 FreePool (HandleBuffer);\r
146 HandleBuffer = NULL;\r
147 }\r
148\r
149 return Status;\r
150}\r
151\r
152/**\r
153 Update the file directly into flash area.\r
154\r
155 @param ConfigData Pointer to the config data on updating file.\r
156 @param ImageBuffer Image buffer to be updated.\r
157 @param ImageSize Image size.\r
158\r
159 @retval EFI_SUCCESS The file is updated into flash area.\r
160 @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found.\r
161\r
162**/\r
163EFI_STATUS\r
164PerformUpdateOnFlashArea (\r
165 IN UPDATE_CONFIG_DATA *ConfigData,\r
166 IN UINT8 *ImageBuffer,\r
167 IN UINTN ImageSize\r
168 )\r
169{\r
170 EFI_STATUS Status;\r
171 UINTN SizeLeft;\r
172 EFI_PHYSICAL_ADDRESS FlashAddress;\r
173 UINT8 *PtrImage;\r
174 BOOLEAN Found;\r
175 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
176 UINTN Index;\r
177 UINTN NumOfHandles;\r
178 EFI_HANDLE *HandleBuffer;\r
179 EFI_PHYSICAL_ADDRESS BaseAddress;\r
180 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
181 EFI_HANDLE FvbHandle;\r
182 UINTN SizeUpdated;\r
183 CHAR16 *TmpStr;\r
184 EFI_FVB_ATTRIBUTES_2 Attributes;\r
185\r
186 SizeLeft = ImageSize;\r
187 PtrImage = ImageBuffer;\r
188 FlashAddress = ConfigData->BaseAddress;\r
189 Status = EFI_SUCCESS;\r
190 HandleBuffer = NULL;\r
191\r
192 //\r
193 // Print on screen\r
194 //\r
195 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL);\r
196 if (TmpStr != NULL) {\r
197 Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress));\r
198 FreePool (TmpStr);\r
199 }\r
0a6f4824 200\r
b2824a8e 201 //\r
202 // Locate all Fvb protocol\r
203 //\r
204 Status = gBS->LocateHandleBuffer (\r
205 ByProtocol,\r
206 &gEfiFirmwareVolumeBlockProtocolGuid,\r
207 NULL,\r
208 &NumOfHandles,\r
209 &HandleBuffer\r
210 );\r
211 if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {\r
212 if (HandleBuffer != NULL) {\r
213 FreePool (HandleBuffer);\r
214 }\r
215 return EFI_NOT_FOUND;\r
216 }\r
217\r
218 while (SizeLeft > 0) {\r
219 //\r
220 // First get the FVB protocols. If the flash area is a FV, or sub FV,\r
221 // we can directly locate all the FVB protocol. Otherwise we should use\r
222 // implementation specific method to get the alternate FVB protocol\r
223 //\r
224 Found = FALSE;\r
225 FvbProtocol = NULL;\r
226\r
227 //\r
228 // Check the FVB protocol one by one\r
229 //\r
230 for (Index = 0; Index < NumOfHandles; Index++) {\r
231 Status = gBS->HandleProtocol (\r
232 HandleBuffer[Index],\r
233 &gEfiFirmwareVolumeBlockProtocolGuid,\r
234 (VOID **) &FvbProtocol\r
235 );\r
236 if (EFI_ERROR (Status)) {\r
237 break;\r
238 }\r
239\r
240 //\r
241 // Ensure this FVB protocol supported Write operation.\r
242 //\r
243 Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);\r
244 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
0a6f4824 245 continue;\r
b2824a8e 246 }\r
247\r
248 Status = FvbProtocol->GetPhysicalAddress (\r
249 FvbProtocol,\r
250 &BaseAddress\r
251 );\r
252 if (EFI_ERROR (Status)) {\r
253 break;\r
254 }\r
255 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;\r
256\r
257 //\r
258 // This sub area entry falls in the range of the FV\r
259 //\r
260 if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) {\r
261 Found = TRUE;\r
262 break;\r
263 }\r
264 }\r
265\r
266 if (!Found) {\r
267 if (HandleBuffer != NULL) {\r
268 FreePool (HandleBuffer);\r
269 HandleBuffer = NULL;\r
270 }\r
271 return EFI_NOT_FOUND;\r
272 }\r
273\r
274 FvbHandle = HandleBuffer[Index];\r
275 SizeUpdated = 0;\r
276\r
277 //\r
278 // If the flash area is boot required, the update must be fault tolerant\r
279 //\r
280 if (ConfigData->FaultTolerant) {\r
281 //\r
282 // Finally we are here. We have got the corresponding FVB protocol. Now\r
283 // we need to convert the physical address to LBA and offset and call\r
284 // FTW write. Also check if the flash range is larger than the FV.\r
285 //\r
286 Status = FaultTolerantUpdateOnPartFv (\r
287 PtrImage,\r
288 SizeLeft,\r
289 &SizeUpdated,\r
290 ConfigData,\r
291 FlashAddress,\r
292 FvbProtocol,\r
293 FvbHandle\r
294 );\r
295 } else {\r
296 //\r
297 // Finally we are here. We have got the corresponding FVB protocol. Now\r
298 // we need to convert the physical address to LBA and offset and call\r
299 // FVB write. Also check if the flash range is larger than the FV.\r
300 //\r
301 Status = NonFaultTolerantUpdateOnPartFv (\r
302 PtrImage,\r
303 SizeLeft,\r
304 &SizeUpdated,\r
305 FlashAddress,\r
306 FvbProtocol,\r
307 FvbHandle\r
308 );\r
309 }\r
310\r
311 if (EFI_ERROR (Status)) {\r
312 return Status;\r
313 }\r
314\r
315 //\r
316 // As part of the FV has been replaced, the FV driver shall re-parse\r
317 // the firmware volume. So re-install FVB protocol here\r
318 //\r
319 Status = gBS->ReinstallProtocolInterface (\r
320 FvbHandle,\r
321 &gEfiFirmwareVolumeBlockProtocolGuid,\r
322 FvbProtocol,\r
323 FvbProtocol\r
324 );\r
325\r
326 if (EFI_ERROR (Status)) {\r
327 return Status;\r
328 }\r
0a6f4824 329\r
b2824a8e 330 //\r
331 // Check if we are done with the update\r
332 //\r
333 SizeLeft = SizeLeft - SizeUpdated;\r
334 FlashAddress = FlashAddress + SizeUpdated;\r
335 PtrImage = PtrImage + SizeUpdated;\r
336 }\r
337\r
338 if (HandleBuffer != NULL) {\r
339 FreePool (HandleBuffer);\r
340 HandleBuffer = NULL;\r
341 }\r
342\r
343 return Status;\r
344}\r
345\r
346/**\r
347 Find the updated file, and program it into the flash area based on the config data.\r
348\r
349 @param FwVolProtocol Pointer to FV protocol that contains the updated file.\r
350 @param ConfigData Pointer to the Config Data on updating file.\r
351\r
352 @retval EFI_INVALID_PARAMETER The update operation is not valid.\r
353 @retval EFI_NOT_FOUND The updated file is not found.\r
354 @retval EFI_SUCCESS The file is updated into the flash area.\r
355\r
356**/\r
357EFI_STATUS\r
358PerformUpdate (\r
359 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol,\r
360 IN UPDATE_CONFIG_DATA *ConfigData\r
361 )\r
362{\r
363 EFI_STATUS Status;\r
364 UINT8 *FileBuffer;\r
365 UINTN FileBufferSize;\r
366 EFI_FV_FILETYPE FileType;\r
367 EFI_FV_FILE_ATTRIBUTES Attrib;\r
368 EFI_SECTION_TYPE SectionType;\r
369 UINT32 AuthenticationStatus;\r
370 CHAR16 *TmpStr;\r
371 BOOLEAN StartToUpdate;\r
372\r
373 Status = EFI_SUCCESS;\r
374 FileBuffer = NULL;\r
375 FileBufferSize = 0;\r
376 Status = FwVolProtocol->ReadFile (\r
377 FwVolProtocol,\r
378 &(ConfigData->FileGuid),\r
379 (VOID **) &FileBuffer,\r
380 &FileBufferSize,\r
381 &FileType,\r
382 &Attrib,\r
383 &AuthenticationStatus\r
384 );\r
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
387 }\r
388\r
389 StartToUpdate = FALSE;\r
390\r
391 //\r
392 // Check if the update image is the one we require\r
393 // and then perform the update\r
394 //\r
395 switch (ConfigData->UpdateType) {\r
396\r
397 case UpdateWholeFV:\r
398\r
399 //\r
400 // For UpdateWholeFv, the update file shall be a firmware volume\r
401 // image file.\r
402 //\r
403 if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
404 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"));\r
405 Status = EFI_INVALID_PARAMETER;\r
406 } else {\r
407 if (FileBuffer != NULL) {\r
408 FreePool (FileBuffer);\r
409 }\r
410 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
411 FileBuffer = NULL;\r
412 FileBufferSize = 0;\r
413 Status = FwVolProtocol->ReadSection (\r
414 FwVolProtocol,\r
415 &(ConfigData->FileGuid),\r
416 SectionType,\r
417 0,\r
418 (VOID **) &FileBuffer,\r
419 &FileBufferSize,\r
420 &AuthenticationStatus\r
421 );\r
422 if (!EFI_ERROR (Status)) {\r
423 //\r
424 // Execute the update. For UpdateWholeFv, the update\r
425 // will always execute on a whole FV\r
426 //\r
427 StartToUpdate = TRUE;\r
428 Status = PerformUpdateOnFirmwareVolume (\r
429 ConfigData,\r
430 FileBuffer,\r
431 FileBufferSize,\r
432 FileType,\r
433 Attrib\r
434 );\r
435\r
436 } else {\r
437 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n"));\r
438 }\r
439 }\r
440 break;\r
441\r
442 case UpdateFvRange:\r
443\r
444 //\r
445 // For UpdateFvRange, the update file shall be a raw file\r
446 // which does not contain any sections. The contents of the file\r
447 // will be directly programmed.\r
448 //\r
449 if (FileType != EFI_FV_FILETYPE_RAW) {\r
450 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n"));\r
451 Status = EFI_INVALID_PARAMETER;\r
452 } else {\r
453 //\r
454 // For UpdateFvRange, the update may be performed on a sub area\r
455 // of a certain FV, or a flash area that is not FV, or part of FV.\r
456 // The update may also go across more than one FVs.\r
457 //\r
458 StartToUpdate = TRUE;\r
459 Status = PerformUpdateOnFlashArea (\r
460 ConfigData,\r
461 FileBuffer,\r
462 FileBufferSize\r
463 );\r
464 }\r
465 break;\r
466\r
467 case UpdateFvFile:\r
468\r
469 //\r
470 // No check will be done the the file got. The contents of the file\r
471 // will be directly programmed.\r
472 // Though UpdateFvFile will only update a single file, but the update\r
473 // will always execute on a FV\r
474 //\r
475 StartToUpdate = TRUE;\r
476 Status = PerformUpdateOnFirmwareVolume (\r
477 ConfigData,\r
478 FileBuffer,\r
479 FileBufferSize,\r
480 FileType,\r
481 Attrib\r
482 );\r
483 break;\r
484\r
485 default:\r
486 Status = EFI_INVALID_PARAMETER;\r
487 }\r
488\r
489 if (StartToUpdate) {\r
490 if (EFI_ERROR (Status)) {\r
491 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL);\r
492 } else {\r
493 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL);\r
494 }\r
495 if (TmpStr != NULL) {\r
496 Print (TmpStr);\r
497 FreePool (TmpStr);\r
498 }\r
499 }\r
500\r
501 if (FileBuffer != NULL) {\r
502 FreePool(FileBuffer);\r
503 FileBuffer = NULL;\r
504 }\r
505\r
506 return Status;\r
507}\r
508\r
509/**\r
510 Process the input firmware volume by using DXE service ProcessFirmwareVolume.\r
511\r
512 @param DataBuffer Point to the FV image to be processed.\r
513 @param BufferSize Size of the FV image buffer.\r
514 @param FwVolProtocol Point to the installed FV protocol for the input FV image.\r
515\r
516 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
517 @retval EFI_VOLUME_CORRUPTED FV image is corrupted.\r
518 @retval EFI_SUCCESS FV image is processed and FV protocol is installed.\r
519\r
520**/\r
521EFI_STATUS\r
522ProcessUpdateImage (\r
523 UINT8 *DataBuffer,\r
524 UINTN BufferSize,\r
525 EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol\r
526 )\r
527{\r
528 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
529 EFI_HANDLE FwVolHandle;\r
530 EFI_STATUS Status;\r
531 UINT8 *ProcessedDataBuffer;\r
532 UINT32 FvAlignment;\r
533\r
534 ProcessedDataBuffer = NULL;\r
535 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer;\r
536 if (FwVolHeader->FvLength != BufferSize) {\r
537 return EFI_VOLUME_CORRUPTED;\r
538 }\r
539\r
540 FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
541 //\r
542 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.\r
0a6f4824 543 //\r
b2824a8e 544 if (FvAlignment < 8) {\r
545 FvAlignment = 8;\r
546 }\r
547 //\r
548 // Check FvImage Align is required.\r
549 //\r
550 if (((UINTN) FwVolHeader % FvAlignment) == 0) {\r
551 ProcessedDataBuffer = DataBuffer;\r
552 } else {\r
553 //\r
554 // Allocate new aligned buffer to store DataBuffer.\r
555 //\r
556 ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
557 if (ProcessedDataBuffer == NULL) {\r
558 return EFI_OUT_OF_RESOURCES;\r
559 }\r
560 CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize);\r
561 }\r
562 //\r
563 // Process the firmware volume\r
564 //\r
565 gDS->ProcessFirmwareVolume (\r
566 ProcessedDataBuffer,\r
567 BufferSize,\r
568 &FwVolHandle\r
569 );\r
570\r
571 //\r
572 // Get the FwVol protocol\r
573 //\r
574 Status = gBS->HandleProtocol (\r
575 FwVolHandle,\r
576 &gEfiFirmwareVolume2ProtocolGuid,\r
577 (VOID **) FwVolProtocol\r
578 );\r
579\r
580 return Status;\r
581}\r
582\r
583/**\r
584 Find the image in the same FV and program it in a target Firmware Volume device.\r
585 After update image, it will reset system and no return.\r
0a6f4824 586\r
b2824a8e 587 @param ImageHandle A handle for the image that is initializing this driver\r
588 @param SystemTable A pointer to the EFI system table\r
589\r
590 @retval EFI_ABORTED System reset failed.\r
591 @retval EFI_NOT_FOUND The updated image is not found in the same FV.\r
592\r
593**/\r
594EFI_STATUS\r
595EFIAPI\r
596InitializeUpdateDriver (\r
597 IN EFI_HANDLE ImageHandle,\r
598 IN EFI_SYSTEM_TABLE *SystemTable\r
599 )\r
600{\r
601 EFI_STATUS Status;\r
602 EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;\r
603 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol;\r
604 EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol;\r
0a6f4824 605 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;\r
b2824a8e 606 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode;\r
607 EFI_DEVICE_PATH_PROTOCOL *FilePathNode;\r
608 EFI_SECTION_TYPE SectionType;\r
609 UINT8 *FileBuffer;\r
610 UINTN FileBufferSize;\r
611 EFI_FV_FILETYPE FileType;\r
612 EFI_FV_FILE_ATTRIBUTES Attrib;\r
613 UINT32 AuthenticationStatus;\r
614 UPDATE_CONFIG_DATA *ConfigData;\r
615 UPDATE_CONFIG_DATA *UpdateConfigData;\r
616 UINTN NumOfUpdates;\r
617 UINTN Index;\r
618 CHAR16 *TmpStr;\r
619\r
620 //\r
621 // Clear screen\r
622 //\r
623 if (gST->ConOut != NULL) {\r
624 gST->ConOut->ClearScreen (gST->ConOut);\r
625 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
626 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
627 }\r
628\r
629 gHiiHandle = HiiAddPackages (\r
630 &gEfiCallerIdGuid,\r
631 NULL,\r
632 UpdateDriverDxeStrings,\r
633 NULL\r
634 );\r
635 ASSERT (gHiiHandle != NULL);\r
636\r
637 //\r
638 // In order to look for the update data file and programmed image file\r
639 // from the same volume which this driver is dispatched from, we need\r
640 // to get the device path of this driver image. It is done by first\r
641 // locate the LoadedImageProtocol and then get its device path\r
642 //\r
643 Status = gBS->OpenProtocol (\r
644 ImageHandle,\r
645 &gEfiLoadedImageProtocolGuid,\r
646 (VOID **)&LoadedImageProtocol,\r
647 ImageHandle,\r
648 NULL,\r
649 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
650 );\r
651 if (EFI_ERROR (Status)) {\r
652 return Status;\r
653 }\r
654 //\r
655 // Get the firmware volume protocol where this file resides\r
656 //\r
657 Status = gBS->HandleProtocol (\r
658 LoadedImageProtocol->DeviceHandle,\r
659 &gEfiFirmwareVolume2ProtocolGuid,\r
660 (VOID **) &FwVolProtocol\r
661 );\r
662 if (EFI_ERROR (Status)) {\r
663 return EFI_NOT_FOUND;\r
664 }\r
665\r
666 //\r
667 // Shall do some extra check to see if it is really contained in the FV?\r
668 // Should be able to find the section of this driver in the the FV.\r
669 //\r
670 FilePathNode = LoadedImageProtocol->FilePath;\r
671 FwVolFilePathNode = NULL;\r
672 while (!IsDevicePathEnd (FilePathNode)) {\r
673 if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) {\r
674 FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode;\r
675 break;\r
676 }\r
677 FilePathNode = NextDevicePathNode (FilePathNode);\r
678 }\r
679\r
680 if (FwVolFilePathNode != NULL) {\r
681 AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode);\r
682\r
683 SectionType = EFI_SECTION_PE32;\r
684 FileBuffer = NULL;\r
685 FileBufferSize = 0;\r
686 Status = FwVolProtocol->ReadSection (\r
687 FwVolProtocol,\r
688 &(AlignedDevPathNode->FvFileName),\r
689 SectionType,\r
690 0,\r
691 (VOID **) &FileBuffer,\r
692 &FileBufferSize,\r
693 &AuthenticationStatus\r
694 );\r
695 if (EFI_ERROR (Status)) {\r
696 FreePool (AlignedDevPathNode);\r
697 return Status;\r
698 }\r
699\r
700 if (FileBuffer != NULL) {\r
701 FreePool(FileBuffer);\r
702 FileBuffer = NULL;\r
703 }\r
704\r
705 //\r
706 // Check the NameGuid of the udpate driver so that it can be\r
707 // used as the CallerId in fault tolerant write protocol\r
708 //\r
709 if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) {\r
710 FreePool (AlignedDevPathNode);\r
711 return EFI_NOT_FOUND;\r
712 }\r
713 FreePool (AlignedDevPathNode);\r
714 } else {\r
715 return EFI_NOT_FOUND;\r
716 }\r
717\r
718 //\r
719 // Now try to find the script file. The script file is usually\r
720 // a raw data file which does not contain any sections.\r
721 //\r
722 FileBuffer = NULL;\r
723 FileBufferSize = 0;\r
724 Status = FwVolProtocol->ReadFile (\r
725 FwVolProtocol,\r
726 &gEfiConfigFileNameGuid,\r
727 (VOID **) &FileBuffer,\r
728 &FileBufferSize,\r
729 &FileType,\r
730 &Attrib,\r
731 &AuthenticationStatus\r
732 );\r
733 if (EFI_ERROR (Status)) {\r
734 return Status;\r
735 }\r
736 if (FileType != EFI_FV_FILETYPE_RAW) {\r
737 return EFI_NOT_FOUND;\r
738 }\r
739\r
740 //\r
741 // Parse the configuration file.\r
742 //\r
743 ConfigData = NULL;\r
744 NumOfUpdates = 0;\r
745 Status = ParseUpdateDataFile (\r
746 FileBuffer,\r
747 FileBufferSize,\r
748 &NumOfUpdates,\r
749 &ConfigData\r
750 );\r
751 if (FileBuffer != NULL) {\r
752 FreePool (FileBuffer);\r
753 FileBuffer = NULL;\r
754 }\r
755 if (EFI_ERROR (Status)) {\r
756 return Status;\r
757 }\r
45295cf5 758 ASSERT (ConfigData != NULL);\r
b2824a8e 759\r
760 //\r
761 // Now find the update image. The update image should be put in a FV, and then\r
762 // encapsulated as a raw FFS file. This is to prevent the update image from\r
763 // being dispatched. So the raw data we get here should be an FV. We need to\r
764 // process this FV and read the files that is going to be updated.\r
765 //\r
766 FileBuffer = NULL;\r
767 FileBufferSize = 0;\r
768 Status = FwVolProtocol->ReadFile (\r
769 FwVolProtocol,\r
e24fc103 770 &gEfiUpdateDataFileGuid,\r
b2824a8e 771 (VOID **) &FileBuffer,\r
772 &FileBufferSize,\r
773 &FileType,\r
774 &Attrib,\r
775 &AuthenticationStatus\r
776 );\r
777 if (EFI_ERROR (Status)) {\r
778 return Status;\r
779 }\r
780 if (FileType != EFI_FV_FILETYPE_RAW) {\r
781 return EFI_NOT_FOUND;\r
782 }\r
783\r
784 //\r
785 // FileBuffer should be an FV. Process the FV\r
786 //\r
787 DataFwVolProtocol = NULL;\r
788 Status = ProcessUpdateImage (\r
789 FileBuffer,\r
790 FileBufferSize,\r
791 &DataFwVolProtocol\r
792 );\r
793 if (EFI_ERROR (Status)) {\r
794 FreePool (FileBuffer);\r
795 return Status;\r
796 }\r
797\r
798 //\r
799 // Print on screen\r
800 //\r
801 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL);\r
802 if (TmpStr != NULL) {\r
803 Print (TmpStr);\r
804 FreePool(TmpStr);\r
805 }\r
806\r
807 //\r
808 // Execute the update\r
809 //\r
810 Index = 0;\r
811 UpdateConfigData = ConfigData;\r
812 while (Index < NumOfUpdates) {\r
813 Status = PerformUpdate (\r
814 DataFwVolProtocol,\r
815 UpdateConfigData\r
816 );\r
817 //\r
0a6f4824 818 // Shall updates be serialized so that if an update is not successfully completed,\r
b2824a8e 819 // the remaining updates won't be performed.\r
820 //\r
821 if (EFI_ERROR (Status)) {\r
822 break;\r
823 }\r
824\r
825 Index++;\r
826 UpdateConfigData++;\r
827 }\r
828\r
829 if (EFI_ERROR (Status)) {\r
830 if (ConfigData != NULL) {\r
831 FreePool(ConfigData);\r
832 ConfigData = NULL;\r
833 }\r
834 return Status;\r
835 }\r
836\r
837 //\r
838 // Call system reset\r
839 //\r
840 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
841\r
842 //\r
843 // Hopefully it won't be reached\r
844 //\r
845 return EFI_ABORTED;\r
846}\r