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