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