]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Vlv2TbltDevicePkg/Application/FirmwareUpdate/FirmwareUpdate.c
Vlv2TbltDevicePkg: Sync the branch changes to Trunk,
[mirror_edk2.git] / Vlv2TbltDevicePkg / Application / FirmwareUpdate / FirmwareUpdate.c
... / ...
CommitLineData
1/** @file\r
2\r
3Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
4 \r\r
5 This program and the accompanying materials are licensed and made available under\r\r
6 the terms and conditions of the BSD License that accompanies this distribution. \r\r
7 The full text of the license may be found at \r\r
8 http://opensource.org/licenses/bsd-license.php. \r\r
9 \r\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
12 \r\r
13\r
14**/\r
15\r
16#include "FirmwareUpdate.h"\r
17\r
18EFI_HII_HANDLE HiiHandle;\r
19\r
20//\r
21// MinnowMax Flash Layout\r
22//\r
23//Start (hex) End (hex) Length (hex) Area Name\r
24//----------- --------- ------------ ---------\r
25//00000000 007FFFFF 00800000 Flash Image\r
26//\r
27//00000000 00000FFF 00001000 Descriptor Region\r
28//00001000 003FFFFF 003FF000 TXE Region\r
29//00500000 007FFFFF 00400000 BIOS Region\r
30//\r
31FV_REGION_INFO mRegionInfo[] = {\r
32 {FixedPcdGet32 (PcdFlashDescriptorBase), FixedPcdGet32 (PcdFlashDescriptorSize), TRUE},\r
33 {FixedPcdGet32 (PcdTxeRomBase), FixedPcdGet32 (PcdTxeRomSize), TRUE},\r
34 {FixedPcdGet32 (PcdBiosRomBase), FixedPcdGet32 (PcdBiosRomSize), TRUE}\r
35};\r
36\r
37UINTN mRegionInfoCount = sizeof (mRegionInfo) / sizeof (mRegionInfo[0]);\r
38\r
39FV_INPUT_DATA mInputData = {0};\r
40\r
41EFI_SPI_PROTOCOL *mSpiProtocol;\r
42\r
43EFI_STATUS\r
44GetRegionIndex (\r
45 IN EFI_PHYSICAL_ADDRESS Address,\r
46 OUT UINTN *RegionIndex\r
47 )\r
48{\r
49 UINTN Index;\r
50\r
51 for (Index = 0; Index < mRegionInfoCount; Index++) {\r
52 if (Address >= mRegionInfo[Index].Base &&\r
53 Address < (mRegionInfo[Index].Base + mRegionInfo[Index].Size)\r
54 ) {\r
55 break;\r
56 }\r
57 }\r
58\r
59 *RegionIndex = Index;\r
60 if (Index >= mRegionInfoCount) {\r
61 return EFI_NOT_FOUND;\r
62 }\r
63 return EFI_SUCCESS;\r
64}\r
65\r
66BOOLEAN\r
67UpdateBlock (\r
68 IN EFI_PHYSICAL_ADDRESS Address\r
69 )\r
70{\r
71 EFI_STATUS Status;\r
72 UINTN Index;\r
73\r
74 if (mInputData.FullFlashUpdate) {\r
75 return TRUE;\r
76 }\r
77\r
78 Status = GetRegionIndex (Address, &Index);\r
79 if ((!EFI_ERROR(Status)) && mRegionInfo[Index].Update) {\r
80 return TRUE;\r
81 }\r
82\r
83 return FALSE;\r
84}\r
85\r
86EFI_STATUS\r
87MarkRegionState (\r
88 IN EFI_PHYSICAL_ADDRESS Address,\r
89 IN BOOLEAN Update\r
90 )\r
91{\r
92 EFI_STATUS Status;\r
93 UINTN Index;\r
94\r
95 Status = GetRegionIndex (Address, &Index);\r
96 if (!EFI_ERROR(Status)) {\r
97 mRegionInfo[Index].Update = Update;\r
98 }\r
99\r
100 return Status;\r
101}\r
102\r
103UINTN\r
104InternalPrintToken (\r
105 IN CONST CHAR16 *Format,\r
106 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console,\r
107 IN VA_LIST Marker\r
108 )\r
109{\r
110 EFI_STATUS Status;\r
111 UINTN Return;\r
112 CHAR16 *Buffer;\r
113 UINTN BufferSize;\r
114\r
115 ASSERT (Format != NULL);\r
116 ASSERT (((UINTN) Format & BIT0) == 0);\r
117 ASSERT (Console != NULL);\r
118\r
119 BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
120\r
121 Buffer = (CHAR16 *) AllocatePool(BufferSize);\r
122 ASSERT (Buffer != NULL);\r
123\r
124 Return = UnicodeVSPrint (Buffer, BufferSize, Format, Marker);\r
125\r
126 if (Console != NULL && Return > 0) {\r
127 //\r
128 // To be extra safe make sure Console has been initialized.\r
129 //\r
130 Status = Console->OutputString (Console, Buffer);\r
131 if (EFI_ERROR (Status)) {\r
132 Return = 0;\r
133 }\r
134 }\r
135\r
136 FreePool (Buffer);\r
137\r
138 return Return;\r
139}\r
140\r
141UINTN\r
142EFIAPI\r
143PrintToken (\r
144 IN UINT16 Token,\r
145 IN EFI_HII_HANDLE Handle,\r
146 ...\r
147 )\r
148{\r
149 VA_LIST Marker;\r
150 UINTN Return;\r
151 CHAR16 *Format;\r
152\r
153 VA_START (Marker, Handle);\r
154\r
155 Format = HiiGetString (Handle, Token, NULL);\r
156 ASSERT (Format != NULL);\r
157\r
158 Return = InternalPrintToken (Format, gST->ConOut, Marker);\r
159\r
160 FreePool (Format);\r
161\r
162 VA_END (Marker);\r
163\r
164 return Return;\r
165}\r
166\r
167EFI_STATUS\r
168ParseCommandLine (\r
169 IN UINTN Argc,\r
170 IN CHAR16 **Argv\r
171 )\r
172{\r
173 EFI_STATUS Status;\r
174 UINTN Index;\r
175\r
176 //\r
177 // Check to make sure that the command line has enough arguments for minimal\r
178 // operation. The minimum is just the file name.\r
179 //\r
180 if (Argc < 2 || Argc > 4) {\r
181 return EFI_INVALID_PARAMETER;\r
182 }\r
183\r
184 //\r
185 // Loop through command line arguments.\r
186 //\r
187 for (Index = 1; Index < Argc; Index++) {\r
188 //\r
189 // Make sure the string is valid.\r
190 //\r
191 if (StrLen (Argv[Index]) == 0) {;\r
192 PrintToken (STRING_TOKEN (STR_FWUPDATE_ZEROLENGTH_ARG), HiiHandle);\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195\r
196 //\r
197 // Check to see if this is an option or the file name.\r
198 //\r
199 if ((Argv[Index])[0] == L'-' || (Argv[Index])[0] == L'/') {\r
200 //\r
201 // Parse the arguments.\r
202 //\r
203 if ((StrCmp (Argv[Index], L"-h") == 0) ||\r
204 (StrCmp (Argv[Index], L"--help") == 0) ||\r
205 (StrCmp (Argv[Index], L"/?") == 0) ||\r
206 (StrCmp (Argv[Index], L"/h") == 0)) {\r
207 //\r
208 // Print Help Information.\r
209 //\r
210 return EFI_INVALID_PARAMETER;\r
211 } else if (StrCmp (Argv[Index], L"-m") == 0) {\r
212 //\r
213 // Parse the MAC address here.\r
214 //\r
215 Status = ConvertMac(Argv[Index+1]);\r
216 if (EFI_ERROR(Status)) {\r
217 PrintToken (STRING_TOKEN (STR_FWUPDATE_INVAILD_MAC), HiiHandle);\r
218 return Status;\r
219 }\r
220\r
221 //\r
222 // Save the MAC address to mInputData.MacValue.\r
223 //\r
224 mInputData.UpdateMac= TRUE;\r
225 Index++;\r
226 } else {\r
227 //\r
228 // Invalid option was provided.\r
229 //\r
230 return EFI_INVALID_PARAMETER;\r
231 }\r
232 }\r
233 if ((Index == Argc - 1) && (StrCmp (Argv[Index - 1], L"-m") != 0)) {\r
234 //\r
235 // The only parameter that is not an option is the firmware image. Check\r
236 // to make sure that the file exists.\r
237 //\r
238 Status = ShellIsFile (Argv[Index]);\r
239 if (EFI_ERROR (Status)) {\r
240 PrintToken (STRING_TOKEN (STR_FWUPDATE_FILE_NOT_FOUND_ERROR), HiiHandle, Argv[Index]);\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243 if (StrLen (Argv[Index]) > INPUT_STRING_LEN) {\r
244 PrintToken (STRING_TOKEN (STR_FWUPDATE_PATH_ERROR), HiiHandle, Argv[Index]);\r
245 return EFI_INVALID_PARAMETER;\r
246 }\r
247 StrCpy (mInputData.FileName, Argv[Index]);\r
248 mInputData.UpdateFromFile = TRUE;\r
249 }\r
250 }\r
251\r
252 return EFI_SUCCESS;\r
253}\r
254\r
255INTN\r
256EFIAPI\r
257ShellAppMain (\r
258 IN UINTN Argc,\r
259 IN CHAR16 **Argv\r
260 )\r
261{\r
262 EFI_STATUS Status;\r
263 UINTN Index;\r
264 UINT32 FileSize;\r
265 UINT32 BufferSize;\r
266 UINT8 *FileBuffer;\r
267 UINT8 *Buffer;\r
268 EFI_PHYSICAL_ADDRESS Address;\r
269 UINTN CountOfBlocks;\r
270 EFI_TPL OldTpl;\r
271 BOOLEAN ResetRequired;\r
272 BOOLEAN FlashError;\r
273\r
274 Index = 0;\r
275 FileSize = 0;\r
276 BufferSize = 0;\r
277 FileBuffer = NULL;\r
278 Buffer = NULL;\r
279 Address = 0;\r
280 CountOfBlocks = 0;\r
281 ResetRequired = FALSE;\r
282 FlashError = FALSE;\r
283\r
284 Status = EFI_SUCCESS;\r
285\r
286 mInputData.FullFlashUpdate = TRUE;\r
287\r
288 //\r
289 // Publish our HII data.\r
290 //\r
291 HiiHandle = HiiAddPackages (\r
292 &gEfiCallerIdGuid,\r
293 NULL,\r
294 FirmwareUpdateStrings,\r
295 NULL\r
296 );\r
297 if (HiiHandle == NULL) {\r
298 Status = EFI_OUT_OF_RESOURCES;\r
299 goto Done;\r
300 }\r
301\r
302 //\r
303 // Locate the SPI protocol.\r
304 //\r
305 Status = gBS->LocateProtocol (\r
306 &gEfiSpiProtocolGuid,\r
307 NULL,\r
308 (VOID **)&mSpiProtocol\r
309 );\r
310 if (EFI_ERROR (Status)) {\r
311 PrintToken (STRING_TOKEN (STR_SPI_NOT_FOUND), HiiHandle);\r
312 return EFI_DEVICE_ERROR;\r
313 }\r
314\r
315 //\r
316 // Parse the command line.\r
317 //\r
318 Status = ParseCommandLine (Argc, Argv);\r
319 if (EFI_ERROR (Status)) {\r
320 PrintHelpInfo ();\r
321 Status = EFI_SUCCESS;\r
322 goto Done;\r
323 }\r
324\r
325 //\r
326 // Display sign-on information.\r
327 //\r
328 PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle);\r
329 PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle);\r
330 PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle);\r
331\r
332 //\r
333 // Test to see if the firmware needs to be updated.\r
334 //\r
335 if (mInputData.UpdateFromFile) {\r
336 //\r
337 // Get the file to use in the update.\r
338 //\r
339 PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE), HiiHandle, mInputData.FileName);\r
340 Status = ReadFileData (mInputData.FileName, &FileBuffer, &FileSize);\r
341 if (EFI_ERROR (Status)) {\r
342 PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE_ERROR), HiiHandle, mInputData.FileName);\r
343 goto Done;\r
344 }\r
345\r
346 //\r
347 // Check that the file and flash sizes match.\r
348 //\r
349 if (FileSize != PcdGet32 (PcdFlashChipSize)) {\r
350 PrintToken (STRING_TOKEN (STR_FWUPDATE_SIZE), HiiHandle);\r
351 Status = EFI_UNSUPPORTED;\r
352 goto Done;\r
353 }\r
354\r
355 //\r
356 // Display flash update information.\r
357 //\r
358 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATING_FIRMWARE), HiiHandle);\r
359\r
360 //\r
361 // Update it.\r
362 //\r
363 Buffer = FileBuffer;\r
364 BufferSize = FileSize;\r
365 Address = PcdGet32 (PcdFlashChipBase);\r
366 CountOfBlocks = (UINTN) (BufferSize / BLOCK_SIZE);\r
367\r
368 //\r
369 // Raise TPL to TPL_NOTIFY to block any event handler,\r
370 // while still allowing RaiseTPL(TPL_NOTIFY) within\r
371 // output driver during Print().\r
372 //\r
373 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
374 for (Index = 0; Index < CountOfBlocks; Index++) {\r
375 //\r
376 // Handle block based on address and contents.\r
377 //\r
378 if (!UpdateBlock (Address)) {\r
379 DEBUG((EFI_D_INFO, "Skipping block at 0x%lx\n", Address));\r
380 } else if (!EFI_ERROR (InternalCompareBlock (Address, Buffer))) {\r
381 DEBUG((EFI_D_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));\r
382 } else {\r
383 //\r
384 // Display a dot for each block being updated.\r
385 //\r
386 Print (L".");\r
387\r
388 //\r
389 // Flag that the flash image will be changed and the system must be rebooted\r
390 // to use the change.\r
391 //\r
392 ResetRequired = TRUE;\r
393\r
394 //\r
395 // Make updating process uninterruptable,\r
396 // so that the flash memory area is not accessed by other entities\r
397 // which may interfere with the updating process.\r
398 //\r
399 Status = InternalEraseBlock (Address);\r
400 ASSERT_EFI_ERROR(Status);\r
401 if (EFI_ERROR (Status)) {\r
402 gBS->RestoreTPL (OldTpl);\r
403 FlashError = TRUE;\r
404 goto Done;\r
405 }\r
406 Status = InternalWriteBlock (\r
407 Address,\r
408 Buffer,\r
409 (BufferSize > BLOCK_SIZE ? BLOCK_SIZE : BufferSize)\r
410 );\r
411 if (EFI_ERROR (Status)) {\r
412 gBS->RestoreTPL (OldTpl);\r
413 FlashError = TRUE;\r
414 goto Done;\r
415 }\r
416 }\r
417\r
418 //\r
419 // Move to next block to update.\r
420 //\r
421 Address += BLOCK_SIZE;\r
422 Buffer += BLOCK_SIZE;\r
423 if (BufferSize > BLOCK_SIZE) {\r
424 BufferSize -= BLOCK_SIZE;\r
425 } else {\r
426 BufferSize = 0;\r
427 }\r
428 }\r
429 gBS->RestoreTPL (OldTpl);\r
430\r
431 //\r
432 // Print result of update.\r
433 //\r
434 if (!FlashError) {\r
435 if (ResetRequired) {\r
436 Print (L"\n");\r
437 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_SUCCESS), HiiHandle);\r
438 } else {\r
439 PrintToken (STRING_TOKEN (STR_FWUPDATE_NO_RESET), HiiHandle);\r
440 }\r
441 } else {\r
442 goto Done;\r
443 }\r
444 }\r
445\r
446 //\r
447 // All flash updates are done so see if the system needs to be reset.\r
448 //\r
449 if (ResetRequired && !FlashError) {\r
450 //\r
451 // Update successful.\r
452 //\r
453 for (Index = 5; Index > 0; Index--) {\r
454 PrintToken (STRING_TOKEN (STR_FWUPDATE_SHUTDOWN), HiiHandle, Index);\r
455 gBS->Stall (1000000);\r
456 }\r
457\r
458 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
459 PrintToken (STRING_TOKEN (STR_FWUPDATE_MANUAL_RESET), HiiHandle);\r
460 CpuDeadLoop ();\r
461 }\r
462\r
463Done:\r
464 //\r
465 // Print flash update failure message if error detected.\r
466 //\r
467 if (FlashError) {\r
468 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_FAILED), HiiHandle, Index);\r
469 }\r
470\r
471 //\r
472 // Do cleanup.\r
473 //\r
474 if (HiiHandle != NULL) {\r
475 HiiRemovePackages (HiiHandle);\r
476 }\r
477 if (FileBuffer) {\r
478 gBS->FreePool (FileBuffer);\r
479 }\r
480\r
481 return Status;\r
482}\r
483\r
484STATIC\r
485EFI_STATUS\r
486InternalEraseBlock (\r
487 IN EFI_PHYSICAL_ADDRESS BaseAddress\r
488 )\r
489/*++\r
490\r
491Routine Description:\r
492\r
493 Erase the whole block.\r
494\r
495Arguments:\r
496\r
497 BaseAddress - Base address of the block to be erased.\r
498\r
499Returns:\r
500\r
501 EFI_SUCCESS - The command completed successfully.\r
502 Other - Device error or wirte-locked, operation failed.\r
503\r
504--*/\r
505{\r
506 EFI_STATUS Status;\r
507 UINTN NumBytes;\r
508\r
509 NumBytes = BLOCK_SIZE;\r
510\r
511 Status = SpiFlashBlockErase ((UINTN) BaseAddress, &NumBytes);\r
512\r
513 return Status;\r
514}\r
515\r
516#if 0\r
517STATIC\r
518EFI_STATUS\r
519InternalReadBlock (\r
520 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
521 OUT VOID *ReadBuffer\r
522 )\r
523{\r
524 EFI_STATUS Status;\r
525 UINT32 BlockSize;\r
526\r
527 BlockSize = BLOCK_SIZE;\r
528\r
529 Status = SpiFlashRead ((UINTN) BaseAddress, &BlockSize, ReadBuffer);\r
530\r
531 return Status;\r
532}\r
533#endif\r
534\r
535STATIC\r
536EFI_STATUS\r
537InternalCompareBlock (\r
538 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
539 IN UINT8 *Buffer\r
540 )\r
541{\r
542 EFI_STATUS Status;\r
543 VOID *CompareBuffer;\r
544 UINT32 NumBytes;\r
545 INTN CompareResult;\r
546\r
547 NumBytes = BLOCK_SIZE;\r
548 CompareBuffer = AllocatePool (NumBytes);\r
549 if (CompareBuffer == NULL) {\r
550 Status = EFI_OUT_OF_RESOURCES;\r
551 goto Done;\r
552 }\r
553\r
554 Status = SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer);\r
555 if (EFI_ERROR (Status)) {\r
556 goto Done;\r
557 }\r
558 CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);\r
559 if (CompareResult != 0) {\r
560 Status = EFI_VOLUME_CORRUPTED;\r
561 }\r
562\r
563Done:\r
564 if (CompareBuffer != NULL) {\r
565 FreePool (CompareBuffer);\r
566 }\r
567\r
568 return Status;\r
569}\r
570\r
571STATIC\r
572EFI_STATUS\r
573InternalWriteBlock (\r
574 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
575 IN UINT8 *Buffer,\r
576 IN UINT32 BufferSize\r
577 )\r
578/*++\r
579\r
580Routine Description:\r
581\r
582 Write a block of data.\r
583\r
584Arguments:\r
585\r
586 BaseAddress - Base address of the block.\r
587 Buffer - Data buffer.\r
588 BufferSize - Size of the buffer.\r
589\r
590Returns:\r
591\r
592 EFI_SUCCESS - The command completed successfully.\r
593 EFI_INVALID_PARAMETER - Invalid parameter, can not proceed.\r
594 Other - Device error or wirte-locked, operation failed.\r
595\r
596--*/\r
597{\r
598 EFI_STATUS Status;\r
599\r
600 Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer);\r
601 ASSERT_EFI_ERROR(Status);\r
602 if (EFI_ERROR (Status)) {\r
603 DEBUG((EFI_D_ERROR, "\nFlash write error."));\r
604 return Status;\r
605 }\r
606\r
607 WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE);\r
608\r
609 Status = InternalCompareBlock (BaseAddress, Buffer);\r
610 if (EFI_ERROR (Status)) {\r
611 DEBUG((EFI_D_ERROR, "\nError when writing to BaseAddress %lx with different at offset %x.", BaseAddress, Status));\r
612 } else {\r
613 DEBUG((EFI_D_INFO, "\nVerified data written to Block at %lx is correct.", BaseAddress));\r
614 }\r
615\r
616 return Status;\r
617\r
618}\r
619\r
620STATIC\r
621EFI_STATUS\r
622ReadFileData (\r
623 IN CHAR16 *FileName,\r
624 OUT UINT8 **Buffer,\r
625 OUT UINT32 *BufferSize\r
626 )\r
627{\r
628 EFI_STATUS Status;\r
629 SHELL_FILE_HANDLE FileHandle;\r
630 UINT64 Size;\r
631 VOID *NewBuffer;\r
632 UINTN ReadSize;\r
633\r
634 FileHandle = NULL;\r
635 NewBuffer = NULL;\r
636 Size = 0;\r
637\r
638 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
639 if (EFI_ERROR (Status)) {\r
640 goto Done;\r
641 }\r
642\r
643 Status = FileHandleIsDirectory (FileHandle);\r
644 if (!EFI_ERROR (Status)) {\r
645 Status = EFI_NOT_FOUND;\r
646 goto Done;\r
647 }\r
648\r
649 Status = FileHandleGetSize (FileHandle, &Size);\r
650 if (EFI_ERROR (Status)) {\r
651 goto Done;\r
652 }\r
653\r
654 NewBuffer = AllocatePool ((UINTN) Size);\r
655\r
656 ReadSize = (UINTN) Size;\r
657 Status = FileHandleRead (FileHandle, &ReadSize, NewBuffer);\r
658 if (EFI_ERROR (Status)) {\r
659 goto Done;\r
660 } else if (ReadSize != (UINTN) Size) {\r
661 Status = EFI_INVALID_PARAMETER;\r
662 goto Done;\r
663 }\r
664\r
665Done:\r
666 if (FileHandle != NULL) {\r
667 ShellCloseFile (&FileHandle);\r
668 }\r
669\r
670 if (EFI_ERROR (Status)) {\r
671 if (NewBuffer != NULL) {\r
672 FreePool (NewBuffer);\r
673 }\r
674 } else {\r
675 *Buffer = NewBuffer;\r
676 *BufferSize = (UINT32) Size;\r
677 }\r
678\r
679 return Status;\r
680}\r
681\r
682STATIC\r
683VOID\r
684PrintHelpInfo (\r
685 VOID\r
686 )\r
687/*++\r
688\r
689Routine Description:\r
690\r
691 Print out help information.\r
692\r
693Arguments:\r
694\r
695 None.\r
696\r
697Returns:\r
698\r
699 None.\r
700\r
701--*/\r
702{\r
703 PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle);\r
704 PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle);\r
705 PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle);\r
706\r
707 Print (L"\n");\r
708 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE), HiiHandle);\r
709 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_1), HiiHandle);\r
710 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_2), HiiHandle);\r
711 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_3), HiiHandle);\r
712 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_4), HiiHandle);\r
713\r
714 Print (L"\n");\r
715}\r
716\r
717/**\r
718 Read NumBytes bytes of data from the address specified by\r
719 PAddress into Buffer.\r
720\r
721 @param[in] Address The starting physical address of the read.\r
722 @param[in,out] NumBytes On input, the number of bytes to read. On output, the number\r
723 of bytes actually read.\r
724 @param[out] Buffer The destination data buffer for the read.\r
725\r
726 @retval EFI_SUCCESS Opertion is successful.\r
727 @retval EFI_DEVICE_ERROR If there is any device errors.\r
728\r
729**/\r
730EFI_STATUS\r
731EFIAPI\r
732SpiFlashRead (\r
733 IN UINTN Address,\r
734 IN OUT UINT32 *NumBytes,\r
735 OUT UINT8 *Buffer\r
736 )\r
737{\r
738 EFI_STATUS Status = EFI_SUCCESS;\r
739 UINTN Offset = 0;\r
740\r
741 ASSERT ((NumBytes != NULL) && (Buffer != NULL));\r
742\r
743 Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
744\r
745 Status = mSpiProtocol->Execute (\r
746 mSpiProtocol,\r
747 1, //SPI_READ,\r
748 0, //SPI_WREN,\r
749 TRUE,\r
750 TRUE,\r
751 FALSE,\r
752 Offset,\r
753 BLOCK_SIZE,\r
754 Buffer,\r
755 EnumSpiRegionAll\r
756 );\r
757 return Status;\r
758\r
759}\r
760\r
761/**\r
762 Write NumBytes bytes of data from Buffer to the address specified by\r
763 PAddresss.\r
764\r
765 @param[in] Address The starting physical address of the write.\r
766 @param[in,out] NumBytes On input, the number of bytes to write. On output,\r
767 the actual number of bytes written.\r
768 @param[in] Buffer The source data buffer for the write.\r
769\r
770 @retval EFI_SUCCESS Opertion is successful.\r
771 @retval EFI_DEVICE_ERROR If there is any device errors.\r
772\r
773**/\r
774EFI_STATUS\r
775EFIAPI\r
776SpiFlashWrite (\r
777 IN UINTN Address,\r
778 IN OUT UINT32 *NumBytes,\r
779 IN UINT8 *Buffer\r
780 )\r
781{\r
782 EFI_STATUS Status;\r
783 UINTN Offset;\r
784 UINT32 Length;\r
785 UINT32 RemainingBytes;\r
786\r
787 ASSERT ((NumBytes != NULL) && (Buffer != NULL));\r
788 ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));\r
789\r
790 Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
791\r
792 ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));\r
793\r
794 Status = EFI_SUCCESS;\r
795 RemainingBytes = *NumBytes;\r
796\r
797 while (RemainingBytes > 0) {\r
798 if (RemainingBytes > SIZE_4KB) {\r
799 Length = SIZE_4KB;\r
800 } else {\r
801 Length = RemainingBytes;\r
802 }\r
803 Status = mSpiProtocol->Execute (\r
804 mSpiProtocol,\r
805 SPI_PROG,\r
806 SPI_WREN,\r
807 TRUE,\r
808 TRUE,\r
809 TRUE,\r
810 (UINT32) Offset,\r
811 Length,\r
812 Buffer,\r
813 EnumSpiRegionAll\r
814 );\r
815 if (EFI_ERROR (Status)) {\r
816 break;\r
817 }\r
818 RemainingBytes -= Length;\r
819 Offset += Length;\r
820 Buffer += Length;\r
821 }\r
822\r
823 //\r
824 // Actual number of bytes written.\r
825 //\r
826 *NumBytes -= RemainingBytes;\r
827\r
828 return Status;\r
829}\r
830\r
831/**\r
832 Erase the block starting at Address.\r
833\r
834 @param[in] Address The starting physical address of the block to be erased.\r
835 This library assume that caller garantee that the PAddress\r
836 is at the starting address of this block.\r
837 @param[in] NumBytes On input, the number of bytes of the logical block to be erased.\r
838 On output, the actual number of bytes erased.\r
839\r
840 @retval EFI_SUCCESS. Opertion is successful.\r
841 @retval EFI_DEVICE_ERROR If there is any device errors.\r
842\r
843**/\r
844EFI_STATUS\r
845EFIAPI\r
846SpiFlashBlockErase (\r
847 IN UINTN Address,\r
848 IN UINTN *NumBytes\r
849 )\r
850{\r
851 EFI_STATUS Status;\r
852 UINTN Offset;\r
853 UINTN RemainingBytes;\r
854\r
855 ASSERT (NumBytes != NULL);\r
856 ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashChipBase));\r
857\r
858 Offset = Address - (UINTN)PcdGet32 (PcdFlashChipBase);\r
859\r
860 ASSERT ((*NumBytes % SIZE_4KB) == 0);\r
861 ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashChipSize));\r
862\r
863 Status = EFI_SUCCESS;\r
864 RemainingBytes = *NumBytes;\r
865\r
866 while (RemainingBytes > 0) {\r
867 Status = mSpiProtocol->Execute (\r
868 mSpiProtocol,\r
869 SPI_SERASE,\r
870 SPI_WREN,\r
871 FALSE,\r
872 TRUE,\r
873 FALSE,\r
874 (UINT32) Offset,\r
875 0,\r
876 NULL,\r
877 EnumSpiRegionAll\r
878 );\r
879 if (EFI_ERROR (Status)) {\r
880 break;\r
881 }\r
882 RemainingBytes -= SIZE_4KB;\r
883 Offset += SIZE_4KB;\r
884 }\r
885\r
886 //\r
887 // Actual number of bytes erased.\r
888 //\r
889 *NumBytes -= RemainingBytes;\r
890\r
891 return Status;\r
892}\r
893\r
894EFI_STATUS\r
895EFIAPI\r
896ConvertMac (\r
897 CHAR16 *Str\r
898 )\r
899{\r
900 UINTN Index;\r
901 UINT8 Temp[MAC_ADD_STR_LEN];\r
902\r
903 if (Str == NULL)\r
904 return EFI_INVALID_PARAMETER;\r
905\r
906 if (StrLen(Str) != MAC_ADD_STR_LEN)\r
907 return EFI_INVALID_PARAMETER;\r
908\r
909 for (Index = 0; Index < MAC_ADD_STR_LEN; Index++) {\r
910 if (Str[Index] >= 0x30 && Str[Index] <= 0x39) {\r
911 Temp[Index] = (UINT8)Str[Index] - 0x30;\r
912 } else if (Str[Index] >= 0x41 && Str[Index] <= 0x46) {\r
913 Temp[Index] = (UINT8)Str[Index] - 0x37;\r
914 } else if (Str[Index] >= 0x61 && Str[Index] <= 0x66) {\r
915 Temp[Index] = (UINT8)Str[Index] - 0x57;\r
916 } else {\r
917 return EFI_INVALID_PARAMETER;\r
918 }\r
919 }\r
920\r
921 for (Index = 0; Index < MAC_ADD_BYTE_COUNT; Index++) {\r
922 mInputData.MacValue[Index] = (Temp[2 * Index] << 4) + Temp[2 * Index + 1];\r
923 }\r
924\r
925 return EFI_SUCCESS;\r
926}\r
927\r