版权声明:本文全部是胡说八道,如果你喜欢,可随意转载 https://blog.csdn.net/robinsongsog/article/details/81203822
/** @file
A simple, basic, EDK II native, "hello" application to verify that
we can build applications without LibC.
Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#pragma optimize( "", off )
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/Spi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#define R_PCH_SPI_FADDR 0x08 ///< SPI Flash Address
//
#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds
#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds
#define R_PCH_SMI_EN 0x30
#define B_PCH_SMI_EN_GBL_SMI 0x1
#define B_PCH_SPI_FADDR_MASK 0x07FFFFFF
// #define BIT8 0x0100
/**
Wait execution cycle to complete on the SPI interface.
@param[in] This The SPI protocol instance
@param[in] PchSpiBar0 Spi MMIO base address
@param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check
@retval TRUE SPI cycle completed on the interface.
@retval FALSE Time out while waiting the SPI cycle to complete.
It's not safe to program the next command on the SPI interface.
**/
BOOLEAN
WaitForSpiCycleComplete (
)
{
UINT64 WaitTicks;
UINT64 WaitCount;
UINT32 Data32;
//
// Convert the wait period allowed into to tick count
//
WaitCount = WAIT_TIME / WAIT_PERIOD;
//
// Wait for the SPI cycle to complete.
//
for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
Data32 = MmioRead32 (0xFE010000 + 0x04);
if ((Data32 & 0x0020) == 0) {
MmioWrite32 (0xFE010000 + 0x04, 0x2 | 0x1);
if (((Data32 & 0x2) != 0) ) {
return FALSE;
} else {
return TRUE;
}
}
// PchPmTimerStallRuntimeSafe (SpiInstance->PchAcpiBase, WAIT_PERIOD);
}
return FALSE;
}
/***
Print a welcoming message.
Establishes the main structure of the application.
@retval 0 The application exited normally.
@retval Other An error occurred.
***/
INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
#if 0
Print(L"Hello there fellow Programmer.\n");
Print(L"Welcome to the world of EDK II.\n");
UINT8 Buffer1[0x1000] ;
EFI_STATUS Status;
PCH_SPI_PROTOCOL *mSpiProtocol;
// CpuBreakpoint();
int a = 1;
int b = 2;
int c = a + b;
c = 0;
Status = gBS->LocateProtocol (
&gPchSpiProtocolGuid,
NULL,
(VOID **)&mSpiProtocol
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Print(L"locate protocol success .\n");
Status = mSpiProtocol->FlashRead (
mSpiProtocol,
FlashRegionBios,
(UINT32) 0,
(UINT32) 0x1000,
Buffer1
);
Print(L"buffer1 0x is : 0x%x\n\n", (Buffer1[0x10] ));
Print(L"buffer1 0x is : 0x%x\n\n", (Buffer1[0x11] ));
Print(L"read bios success .\n");
#endif
#if 1
// CpuBreakpoint();
int a = 1;
int b = 2;
int c = a + b;
c = 0;
UINT32 Index;
UINT32 FlashRegionSize;
UINT32 HardwareSpiAddr;
UINT32 SpiDataCount;
UINT32 ByteCount = 0x1000;
UINT8 *Buffer;
UINT16 ABase;
UINT32 SmiEnSave;
UINTN PchSpiBar0;
PchSpiBar0 = 0xFE010000;
Buffer = AllocateZeroPool(0x1000);
UINT8 * Buffer_address_backup;
Buffer_address_backup = Buffer;
ABase= 0x1800;
SmiEnSave = IoRead32 ((UINTN) (ABase + R_PCH_SMI_EN));
// IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
// IoWrite32 ((UINTN) 0x1830, 0x22);
IoWrite32 ((UINTN) (ABase + R_PCH_SMI_EN), SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI));
Print(L"(ABase + R_PCH_SMI_EN = %x.\n", (ABase + R_PCH_SMI_EN));
Print(L"SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI) = %x.\n",SmiEnSave & (UINT32) (~B_PCH_SMI_EN_GBL_SMI) );
HardwareSpiAddr = 0x800000;
FlashRegionSize = 0x800000;
Print(L"io write success .\n");
do {
SpiDataCount = ByteCount;
//
// Trim at 256 byte boundary per operation,
// - PCH SPI controller requires trimming at 4KB boundary
// - Some SPI chips require trimming at 256 byte boundary for write operation
// - Trimming has limited performance impact as we can read / write atmost 64 byte
// per operation
//
if (HardwareSpiAddr + ByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) {
SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr);
}
//
// Calculate the number of bytes to shift in/out during the SPI data cycle.
// Valid settings for the number of bytes duing each data portion of the
// PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
//
if (SpiDataCount >= 64) {
SpiDataCount = 64;
// Print (("SpiDataCount1: 0x%x \n", (UINT32)SpiDataCount));
} else if ((SpiDataCount &~0x07) != 0) {
SpiDataCount = SpiDataCount &~0x07;
// Print (( "SpiDataCount2: 0x%x \n", (UINT32)SpiDataCount));
}
// Print((L"SpiDataCount is : 0x%x\n\n", (UINT32)SpiDataCount ));
// SpiDataCount = 64;
// MmioWrite32 (0xFE010000 + 0x08, HardwareSpiAddr & 0x07FFFFFF);
SpiDataCount = 64;
//
// Set the Flash Address
//
MmioWrite32 (
(PchSpiBar0 + R_PCH_SPI_FADDR),
(UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK)
);
MmioAndThenOr32 (0xFE010004, 0xC0E1FFFF, 0x3F010000);
// Use Dword read if Data Count is 8, 16, 24, 32, 40, 48, 56, 64
//
Print(L"WaitForSpiCycleComplete start.\n");
WaitForSpiCycleComplete();
Print(L"WaitForSpiCycleComplete end.\n");
for (Index = 0; Index < SpiDataCount; Index += sizeof (UINT32)) {
*(UINT32 *) (Buffer + Index) = MmioRead32 (0xFE010000 + 0x10 + Index);
}
HardwareSpiAddr += SpiDataCount;
Buffer += SpiDataCount;
ByteCount -= SpiDataCount;
} while (ByteCount > 0);
// DEBUG ((DEBUG_INFO, "buffer 0x 10 is : 0x%x\n", *(UINT32 *)(Buffer + 0x10));
Print(L"buffer 0x10x is : 0x%x\n\n", *(Buffer_address_backup + 0x10));
Print(L"buffer 0x11x is : 0x%x\n\n", *(UINT8 *)(Buffer_address_backup + 0x11));
#endif
return(0);
}