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