Compare commits

...

17 Commits

Author SHA1 Message Date
860a8d95c2 CorebootPayloadPkg: don't set PcdDebugPropertyMask for release builds
Don't set PcdDebugPropertyMask for release builds, and properly set it
for debug builds based on SOURCE_DEBUG_ENABLE.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-17 15:59:54 -05:00
6105116c48 EmuVariable: only read/write Bootorder variables
Tianocore currently reads/writes a lot of NVRAM variables that
don't actually need to be saved. Occasionally some, specifically
related to the graphical/serial consoles, can become corrupted,
leading to a bricked device. To avoid this, temporarily restrict
the reading/writing of variables to Bootorder related ones
(starting with 'Boot') until a better solution can be found.

Test: build/boot google/eve, inject "bad" NVRAM data, observe
device boots normally instead of hanging with no display detected.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-17 15:59:38 -05:00
77ddbd2deb s76-smmstore: update compiled driver
update compiled driver with one that doesn't hang on systems
built without CONFIG_SMMSTORE=y in coreboot.

Test: build/boot google/kahlee with and w.o SMMSTORE enabled

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-03 22:38:38 -06:00
f15ac4583b MdeModulePkg/SdMmcPciHcDxe: add Bayhub support
Add support for Bayhub eMMC controller found on AMD
Stoneyridge Chromebooks.

Test: build/boot various google/kahlee-based devices

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:27:11 -06:00
daa1f83b55 Add/use System76 firmware-smmstore driver
Add/use System76 firmware-smmstore driver, to compact
the smmstore NVRAM variables. Helps prevent corruption
of NVRAM variables leading to boot hang.

Compiled from system76/firmware-smmstore commit 2e94590

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:26:06 -06:00
1b66efff52 EmuVariable: enable deletion of variables
Make it possible to delete a variable by appending it with
size 0. Also ignore keysizes of 0 when reading variables.

Signed-off-by: Jeremy Soller <jeremy@system76.com>
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:26:06 -06:00
4f60b6a439 BdsPlatform: generate SMM events to put eMMC/SD in proper mode
For Baytrail devices, coreboot leaves the eMMC/SD in PCI mode to enable
detection by Tianocore, so put into ACPI mode before OS boots.
Fixes booting on Baytrail devices.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2020-03-01 13:25:59 -06:00
64f7b0fdba Merge pull request #8 from PatrickRudolph/fix_smm_detect
MdeModulePkg/Universal/Variable/EmuRuntimeDxe: Check SMM store return…
2020-01-08 16:10:14 -06:00
359e78336d MdeModulePkg/Universal/Variable/EmuRuntimeDxe: Check SMM store return codes
Check SMM store return code and return on error.

Fixes significant boot delay in case no SMM store is present.
This can happend quite often if the tianocore payload is build standalone
and patched into a coreboot ROM.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
2020-01-08 13:22:57 +01:00
81f6f9c8e8 Frontpage: add entries for Stoneyridge Chromebooks
Add entries for Aleena, Barla, Careena, Kasumi, Liara.
Remove unused entry for Purism Librem 13v2 since not a
Google device.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-28 12:44:08 -06:00
b98c44e412 MdeModulePkg/Usb/Keyboard: add SetIdle quirk handler
Some USB keyboards, like the Aspeed BMC HID keyboard,
require the SetIdle command to be issued before interrupt
transfers can be enabled. Add a quirk handler so any similar
devices can make use of same function by the addition of the
USB vendor/device IDs.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:57:51 -06:00
f1d5f1091d MdeModulePkg/Usb/Keyboard.c: don't request protocol before setting
No need to check the interface protocol then conditionally setting,
just set it to BOOT_PROTOCOL and check for error.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:56:30 -06:00
2719881a54 MdeModulePkg/Usb/Keyboard.c: remove Get/SetConfig calls
SetConfig is already called during device enumeration,
no need to do it again here.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-17 22:50:56 -06:00
115ed8d16d Prioritize Udf and ElTorito partition types over Mbr to fix ISO boots 2019-12-16 16:24:41 -06:00
8681de13a9 Frontpage: add entry for CAROLINE
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-13 16:00:50 -06:00
1f726fc0cf MdeModulePkg/Usb/UsbMouse: Fix endpoint selection
The endpoint selected by the driver needs to not
only be an interrupt type, but have direction IN
as required to set up an asynchronous interrupt transfer.

Currently, the driver assumes that the first INT endpoint
will be of type IN, but that is not true of all devices,
and will silently fail on devices which have the OUT endpoint
before the IN. Adjust the endpoint selection loop to explictly
check for direction IN.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-12 13:40:46 -06:00
6943792307 MdeModulePkg/Usb/EfiKey: Fix endpoint selection
The endpoint selected by the driver needs to not
only be an interrupt type, but have direction IN
as required to set up an asynchronous interrupt transfer.

Currently, the driver assumes that the first INT endpoint
will be of type IN, but that is not true of all devices,
and will silently fail on devices which have the OUT endpoint
before the IN. Adjust the endpoint selection loop to explictly
check for direction IN.

Test: detachable keyboard on Google Pixel Slate now works.

Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
2019-12-12 13:40:35 -06:00
20 changed files with 964 additions and 108 deletions

View File

@ -1265,6 +1265,11 @@ Returns:
Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000);
ASSERT (Status == EFI_SUCCESS); ASSERT (Status == EFI_SUCCESS);
//
// invoke SMM handler to put eMMC/SD devices into ACPI mode for OS
//
IoWrite8(0xb2, 0xcd);
// //
// To give the User a chance to enter Setup here, if user set TimeOut is 0. // To give the User a chance to enter Setup here, if user set TimeOut is 0.
// BDS should still give user a chance to enter Setup // BDS should still give user a chance to enter Setup

View File

@ -42,6 +42,7 @@ Abstract:
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
#include <Library/DxeServicesTableLib.h> #include <Library/DxeServicesTableLib.h>
#include <Library/DevicePathLib.h> #include <Library/DevicePathLib.h>
#include <Library/IoLib.h>
#include <Protocol/PciIo.h> #include <Protocol/PciIo.h>

View File

@ -110,6 +110,10 @@ INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
!if $(ARCH) == IA32
!else
INF RuleOverride=BINARY USE = X64 CorebootPayloadPkg/s76-smmstore/s76-smmstore.inf
!endif
INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf

View File

@ -293,10 +293,12 @@
[PcdsPatchableInModule.common] [PcdsPatchableInModule.common]
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7 gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
!if $(SOURCE_DEBUG_ENABLE) !if $(TARGET) == DEBUG
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else !else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2B
!endif
!endif !endif
# #

View File

@ -294,10 +294,12 @@
[PcdsPatchableInModule.common] [PcdsPatchableInModule.common]
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7 gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
!if $(SOURCE_DEBUG_ENABLE) !if $(TARGET) == DEBUG
!if $(SOURCE_DEBUG_ENABLE)
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17 gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
!else !else
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2B
!endif
!endif !endif
# #

Binary file not shown.

View File

@ -0,0 +1,9 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = system76-firmware-smmstore
FILE_GUID = 764f0f8d-658b-4d32-a057-b44fb209512c
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
[Binaries.X64]
PE32|s76-smmstore.efi|*

View File

@ -737,6 +737,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 13"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 13");
} else if (!StrCmp(Product, L"Akali 360")) { } else if (!StrCmp(Product, L"Akali 360")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 13"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook Spin 13");
} else if (!StrCmp(Product, L"Aleena")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 315");
} else if (!StrCmp(Product, L"Atlas")) { } else if (!StrCmp(Product, L"Atlas")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixelbook Go 2019"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Google Pixelbook Go 2019");
} else if (!StrCmp(Product, L"Auron")) { } else if (!StrCmp(Product, L"Auron")) {
@ -751,12 +753,18 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 CB5-532"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 15 CB5-532");
} else if (!StrCmp(Product, L"Bard")) { } else if (!StrCmp(Product, L"Bard")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 715"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 715");
} else if (!StrCmp(Product, L"Barla")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 11A G6 EE");
} else if (!StrCmp(Product, L"Buddy")) { } else if (!StrCmp(Product, L"Buddy")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebase 24"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebase 24");
} else if (!StrCmp(Product, L"Butterfly")) { } else if (!StrCmp(Product, L"Butterfly")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pavilion Chromebook 14"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Pavilion Chromebook 14");
} else if (!StrCmp(Product, L"Candy")) { } else if (!StrCmp(Product, L"Candy")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3120"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3120");
} else if (!StrCmp(Product, L"Careena")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"HP Chromebook 14");
} else if (!StrCmp(Product, L"Caroline")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Samsung Chromebook Pro");
} else if (!StrCmp(Product, L"Cave")) { } else if (!StrCmp(Product, L"Cave")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C302"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebook Flip C302");
} else if (!StrCmp(Product, L"Celes")) { } else if (!StrCmp(Product, L"Celes")) {
@ -787,6 +795,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AMD StonyRidge Chromebook"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"AMD StonyRidge Chromebook");
} else if (!StrCmp(Product, L"Guado")) { } else if (!StrCmp(Product, L"Guado")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 2 / CN62"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Asus Chromebox 2 / CN62");
} else if (!StrCmp(Product, L"Kasumi")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 311");
} else if (!StrCmp(Product, L"Kefka")) { } else if (!StrCmp(Product, L"Kefka")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3180/3189"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 11 3180/3189");
} else if (!StrCmp(Product, L"Kench")) { } else if (!StrCmp(Product, L"Kench")) {
@ -797,8 +807,8 @@ GetDeviceNameFromProduct (
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 14 for Work"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Acer Chromebook 14 for Work");
} else if (!StrCmp(Product, L"Leon")) { } else if (!StrCmp(Product, L"Leon")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Toshiba Chromebook");
} else if (!StrCmp(Product, L"Librem 13 v2")) { } else if (!StrCmp(Product, L"Liara")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Purism Librem 13 v2"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Lenovo 14e Chromebook");
} else if (!StrCmp(Product, L"Lulu")) { } else if (!StrCmp(Product, L"Lulu")) {
StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 13 7310"); StrCatS (*DeviceName, 0x60 / sizeof (CHAR16), L"Dell Chromebook 13 7310");
} else if (!StrCmp(Product, L"Link")) { } else if (!StrCmp(Product, L"Link")) {

174
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c Executable file → Normal file
View File

@ -526,16 +526,35 @@ EmmcTuningClkForHs200 (
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if(BhtHostPciSupport(PciIo)) {
//set data transfer with 4bit
Status = SdMmcHcSetBusWidth (PciIo, Slot, 4);
//enable hardware tuning
HostCtrl2 = (UINT8)(~0x10);
Status = SdMmcHcAndMmio (PciIo, Slot, 0x110,sizeof (HostCtrl2), &HostCtrl2);
Status = EmmcSendTuningBlk (PassThru, Slot, 4);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
return Status;
}
}
// //
// Ask the device to send a sequence of tuning blocks till the tuning procedure is done. // Ask the device to send a sequence of tuning blocks till the tuning procedure is done.
// //
Retry = 0; Retry = 0;
do { do {
if(!BhtHostPciSupport(PciIo)) {
Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth); Status = EmmcSendTuningBlk (PassThru, Slot, BusWidth);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status)); DEBUG ((DEBUG_ERROR, "EmmcTuningClkForHs200: Send tuning block fails with %r\n", Status));
return Status; return Status;
} }
} else {
gBS->Stall(5000);
}
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2); Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, TRUE, sizeof (HostCtrl2), &HostCtrl2);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -547,6 +566,10 @@ EmmcTuningClkForHs200 (
} }
if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) { if ((HostCtrl2 & (BIT6 | BIT7)) == BIT7) {
if(BhtHostPciSupport(PciIo)) {
//set data transfer with default
Status = SdMmcHcSetBusWidth (PciIo, Slot, BusWidth);
}
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} while (++Retry < 40); } while (++Retry < 40);
@ -770,10 +793,21 @@ EmmcSwitchToHighSpeed (
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
DbgMsg("switch to HS mode %dMHz\n", ClockFreq);
Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth); Status = EmmcSwitchBusWidth (PciIo, PassThru, Slot, Rca, IsDdr, BusWidth);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if (BhtHostPciSupport(PciIo)) {
HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
}
// //
// Set to Hight Speed timing // Set to Hight Speed timing
// //
@ -796,8 +830,10 @@ EmmcSwitchToHighSpeed (
return Status; return Status;
} }
if (!BhtHostPciSupport(PciIo)) {
HsTiming = 1; HsTiming = 1;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq); Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
}
return Status; return Status;
} }
@ -837,6 +873,8 @@ EmmcSwitchToHS200 (
Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru);
DbgMsg("switch to HS200 mode %dMHz\n", ClockFreq);
if ((BusWidth != 4) && (BusWidth != 8)) { if ((BusWidth != 4) && (BusWidth != 8)) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
@ -845,6 +883,15 @@ EmmcSwitchToHS200 (
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if (BhtHostPciSupport(PciIo)){
HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) {
return Status;
}
}
// //
// Set to HS200/SDR104 timing // Set to HS200/SDR104 timing
// //
@ -866,6 +913,17 @@ EmmcSwitchToHS200 (
// //
// Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit // Wait Internal Clock Stable in the Clock Control register to be 1 before set SD Clock Enable bit
// //
if (BhtHostPciSupport(PciIo)) {
Status = SdMmcHcWaitMmioSet (
PciIo,
Slot,
0x1cc,
sizeof (ClockCtrl),
BIT14,
BIT14,
SD_MMC_HC_GENERIC_TIMEOUT
);
} else {
Status = SdMmcHcWaitMmioSet ( Status = SdMmcHcWaitMmioSet (
PciIo, PciIo,
Slot, Slot,
@ -875,22 +933,53 @@ EmmcSwitchToHS200 (
BIT1, BIT1,
SD_MMC_HC_GENERIC_TIMEOUT SD_MMC_HC_GENERIC_TIMEOUT
); );
}
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if (BhtHostPciSupport(PciIo)) {
//Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
UINT32 value32;
while (1) {
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
if (((value32 >> 18) & 0x01) == ((value32 >> 16) & 0x01)) {
break;
}
}
}
// //
// Set SD Clock Enable in the Clock Control register to 1 // Set SD Clock Enable in the Clock Control register to 1
// //
ClockCtrl = BIT2; ClockCtrl = BIT2;
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl); Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL, sizeof (ClockCtrl), &ClockCtrl);
if (!BhtHostPciSupport(PciIo)) {
HsTiming = 2; HsTiming = 2;
Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq); Status = EmmcSwitchClockFreq (PciIo, PassThru, Slot, Rca, HsTiming, Timing, ClockFreq);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
} else {
Status = SdMmcHcWaitMmioSet (
PciIo,
Slot,
0x1cc,
sizeof (ClockCtrl),
BIT11,
BIT11,
SD_MMC_CLOCK_STABLE_TIMEOUT
);
if (EFI_ERROR(Status)) {
DbgMsg("Wait Clock Stable timeout, ClockFreq=%d\n", ClockFreq);
return Status;
}
}
Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth); Status = EmmcTuningClkForHs200 (PciIo, PassThru, Slot, BusWidth);
if (EFI_ERROR(Status)) {
DbgMsg("Emmc tuning failed\n");
}
return Status; return Status;
} }
@ -1068,6 +1157,37 @@ EmmcSetBusMode (
DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE")); DEBUG ((DEBUG_INFO, "EmmcSetBusMode: HsTiming %d ClockFreq %d BusWidth %d Ddr %a\n", HsTiming, ClockFreq, BusWidth, IsDdr ? "TRUE":"FALSE"));
if (BhtHostPciSupport(PciIo)) {
UINT8 EmmcVar;
UINTN EmmcVarSize;
Status = gRT->GetVariable (
L"EMMC_FORCE_CARD_MODE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (!EFI_ERROR(Status) && EmmcVar <= 2) {
if (EmmcVar == 2) {
HsTiming = 2;
IsDdr = FALSE;
ClockFreq = 200;
} else if (EmmcVar == 1) {
HsTiming = 2;
IsDdr = FALSE;
ClockFreq = 100;
} else {
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 52;
}
} else {
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 52;
}
}
if (HsTiming == 3) { if (HsTiming == 3) {
// //
// Execute HS400 timing switch procedure // Execute HS400 timing switch procedure
@ -1078,6 +1198,60 @@ EmmcSetBusMode (
// Execute HS200 timing switch procedure // Execute HS200 timing switch procedure
// //
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth); Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
if (EFI_ERROR(Status)) {
if (BhtHostPciSupport(PciIo)) {
UINT32 val32;
UINT16 EmmcVar;
UINTN EmmcVarSize;
DbgMsg("switch to HS200 200MHZ failed, freq decrease to 100MHz\n");
#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0
#error "HS100_ALLPASS_PHASE is undefined or value is invalid"
#else
val32 = PciBhtRead32(PciIo, 0x300);
val32 &= 0xFF0FFFFF;
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS100_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS100_ALLPASS_PHASE;
val32 |= (EmmcVar << 20);
PciBhtWrite32(PciIo, 0x300, 0x21000033 | val32);
#endif
ClockFreq = 100;
SdMmcHcRwMmio (PciIo, Slot, 0x3C, TRUE, sizeof(val32), &val32);
val32 &= ~BIT22;
SdMmcHcRwMmio (PciIo, Slot, 0x3C, FALSE, sizeof(val32), &val32);
val32 = (BIT26 | BIT25);
SdMmcHcOrMmio (PciIo, Slot, 0x2C, sizeof(val32), &val32);
Status = EmmcSwitchToHS200 (PciIo, PassThru, Slot, Rca, ClockFreq, BusWidth);
if (EFI_ERROR(Status)) {
if (((ExtCsd.DeviceType & BIT1) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
DbgMsg("switch to HS200 100MHZ failed, mode decrease to HS 50MHz\n");
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 52;
Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
} else if (((ExtCsd.DeviceType & BIT0) != 0) && (Private->Capability[Slot].HighSpeed != 0)) {
DbgMsg("switch to HS200 100MHZ failed, mode decrease to HS 25MHz\n");
HsTiming = 1;
IsDdr = FALSE;
ClockFreq = 26;
Status = EmmcSwitchToHighSpeed (PciIo, PassThru, Slot, Rca, ClockFreq, IsDdr, BusWidth);
} else {
DbgMsg("switch to HS200 100MHZ failed, but emmc chip didn't support hs mode\n");
}
}
}
}
} else { } else {
// //
// Execute High Speed timing switch procedure // Execute High Speed timing switch procedure

View File

@ -295,6 +295,13 @@ SdMmcPciHcEnumerateDevice (
continue; continue;
} }
if (BhtHostPciSupport(Private->PciIo)) {
Status = SdMmcHcGetCapability (Private->PciIo, Slot, &Private->Capability[Slot]);
if (EFI_ERROR (Status)) {
continue;
}
}
Private->Slot[Slot].MediaPresent = TRUE; Private->Slot[Slot].MediaPresent = TRUE;
Private->Slot[Slot].Initialized = TRUE; Private->Slot[Slot].Initialized = TRUE;
RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE); RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
@ -311,6 +318,7 @@ SdMmcPciHcEnumerateDevice (
// This card doesn't get initialized correctly. // This card doesn't get initialized correctly.
// //
if (Index == RoutineNum) { if (Index == RoutineNum) {
DEBUG ((DEBUG_INFO, "Load driver failure\n"));
Private->Slot[Slot].Initialized = FALSE; Private->Slot[Slot].Initialized = FALSE;
} }
@ -530,6 +538,8 @@ SdMmcPciHcDriverBindingStart (
UINT32 RoutineNum; UINT32 RoutineNum;
BOOLEAN MediaPresent; BOOLEAN MediaPresent;
BOOLEAN Support64BitDma; BOOLEAN Support64BitDma;
UINT16 IntStatus;
UINT32 value;
DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n")); DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n"));
@ -685,6 +695,13 @@ SdMmcPciHcDriverBindingStart (
continue; continue;
} }
if (BhtHostPciSupport(PciIo)) {
Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]);
if (EFI_ERROR (Status)) {
continue;
}
}
Private->Slot[Slot].MediaPresent = TRUE; Private->Slot[Slot].MediaPresent = TRUE;
Private->Slot[Slot].Initialized = TRUE; Private->Slot[Slot].Initialized = TRUE;
RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE); RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE);
@ -701,9 +718,52 @@ SdMmcPciHcDriverBindingStart (
// This card doesn't get initialized correctly. // This card doesn't get initialized correctly.
// //
if (Index == RoutineNum) { if (Index == RoutineNum) {
DEBUG ((DEBUG_INFO, "Load driver failure\n"));
Private->Slot[Slot].Initialized = FALSE; Private->Slot[Slot].Initialized = FALSE;
} }
} }
if (BhtHostPciSupport(Private->PciIo)) {
DbgMsg("HOST_CLK_DRIVE_STRENGTH: 0x%x\n",HOST_CLK_DRIVE_STRENGTH);
DbgMsg("HOST_DAT_DRIVE_STRENGTH: 0x%x\n",HOST_DAT_DRIVE_STRENGTH);
DbgMsg("HS200_ALLPASS_PHASE: 0x%x\n",HS200_ALLPASS_PHASE);
DbgMsg("HS100_ALLPASS_PHASE: 0x%x\n",HS100_ALLPASS_PHASE);
SdMmcHcRwMmio (Private->PciIo,0,0x110,TRUE,sizeof (value),&value);
DbgMsg("0x110: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x114,TRUE,sizeof (value),&value);
DbgMsg("0x114: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1a8,TRUE,sizeof (value),&value);
DbgMsg("MEM 1A8: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1ac,TRUE,sizeof (value),&value);
DbgMsg("MEM 1AC: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1B0,TRUE,sizeof (value),&value);
DbgMsg("MEM 1B0: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,0x1CC,TRUE,sizeof (value),&value);
DbgMsg("MEM 1CC: 0x%x\n",value);
DbgMsg(" - pcr 0x300 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x300));
DbgMsg(" - pcr 0x304 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x304));
DbgMsg(" - pcr 0x328 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x328));
DbgMsg(" - pcr 0x3e4 = 0x%08x\n", PciBhtRead32(Private->PciIo, 0x3e4));
SdMmcHcRwMmio (Private->PciIo,0,0x040,TRUE,sizeof (value),&value);
DbgMsg("0x40: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_PRESENT_STATE,TRUE,sizeof (value),&value);
DbgMsg("Present State: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL1,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("Power&Host1: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_CLOCK_CTRL,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("CLK: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_TIMEOUT_CTRL,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("SWR&Timeout: 0x%x\n",IntStatus);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_NOR_INT_STS,TRUE,sizeof (value),&value);
DbgMsg("INR&IER: 0x%x\n",value);
SdMmcHcRwMmio (Private->PciIo,0,SD_MMC_HC_HOST_CTRL2,TRUE,sizeof (IntStatus),&IntStatus);
DbgMsg("Host2: 0x%x\n",IntStatus);
}
// //
// Enable 64-bit DMA support in the PCI layer if this controller // Enable 64-bit DMA support in the PCI layer if this controller

View File

@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/UefiDriverEntryPoint.h> #include <Library/UefiDriverEntryPoint.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h> #include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h> #include <Library/MemoryAllocationLib.h>
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
@ -38,6 +39,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SdMmcOverride.h> #include <Protocol/SdMmcOverride.h>
#include <Protocol/SdMmcPassThru.h> #include <Protocol/SdMmcPassThru.h>
#include <Guid/DebugMask.h>
#include "SdMmcPciHci.h" #include "SdMmcPciHci.h"
extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName; extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName;
@ -51,10 +54,16 @@ extern EDKII_SD_MMC_OVERRIDE *mOverride;
#define SD_MMC_HC_PRIVATE_FROM_THIS(a) \ #define SD_MMC_HC_PRIVATE_FROM_THIS(a) \
CR(a, SD_MMC_HC_PRIVATE_DATA, PassThru, SD_MMC_HC_PRIVATE_SIGNATURE) CR(a, SD_MMC_HC_PRIVATE_DATA, PassThru, SD_MMC_HC_PRIVATE_SIGNATURE)
#define HOST_CLK_DRIVE_STRENGTH 2
#define HOST_DAT_DRIVE_STRENGTH 2
#define HS200_ALLPASS_PHASE 0
#define HS100_ALLPASS_PHASE 6
// //
// Generic time out value, 1 microsecond as unit. // Generic time out value, 1 microsecond as unit.
// //
#define SD_MMC_HC_GENERIC_TIMEOUT 1 * 1000 * 1000 #define SD_MMC_HC_GENERIC_TIMEOUT 1 * 1000 * 1000
#define SD_MMC_CLOCK_STABLE_TIMEOUT 3 * 1000
// //
// SD/MMC async transfer timer interval, set by experience. // SD/MMC async transfer timer interval, set by experience.

View File

@ -18,12 +18,12 @@
## ##
[Defines] [Defines]
INF_VERSION = 0x00010005 INF_VERSION = 0x00010007
BASE_NAME = SdMmcPciHcDxe BASE_NAME = SdMmcPciHcDxe
MODULE_UNI_FILE = SdMmcPciHcDxe.uni MODULE_UNI_FILE = SdMmcPciHcDxe.uni
FILE_GUID = 8E325979-3FE1-4927-AAE2-8F5C4BD2AF0D FILE_GUID = 8E325979-3FE1-4927-AAE2-8F5C4BD2AF0D
MODULE_TYPE = UEFI_DRIVER MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0 VERSION_STRING = 1.5.4
ENTRY_POINT = InitializeSdMmcPciHcDxe ENTRY_POINT = InitializeSdMmcPciHcDxe
# #
@ -67,6 +67,9 @@
gEfiPciIoProtocolGuid ## TO_START gEfiPciIoProtocolGuid ## TO_START
gEfiSdMmcPassThruProtocolGuid ## BY_START gEfiSdMmcPassThruProtocolGuid ## BY_START
[Guids]
gEfiGenericVariableGuid
# [Event] # [Event]
# EVENT_TYPE_PERIODIC_TIMER ## SOMETIMES_CONSUMES # EVENT_TYPE_PERIODIC_TIMER ## SOMETIMES_CONSUMES

View File

@ -17,6 +17,9 @@
#include "SdMmcPciHcDxe.h" #include "SdMmcPciHcDxe.h"
int g_deviceId = 0;
/** /**
Dump the content of SD/MMC host controller's Capability Register. Dump the content of SD/MMC host controller's Capability Register.
@ -1031,6 +1034,15 @@ SdMmcHcInitPowerVoltage (
// Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register // Set SD Bus Voltage Select and SD Bus Power fields in Power Control Register
// //
Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage); Status = SdMmcHcPowerControl (PciIo, Slot, MaxVoltage);
if (BhtHostPciSupport(PciIo)){
// 1.8V signaling enable
HostCtrl2 = BIT3;
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_HOST_CTRL2, sizeof (HostCtrl2), &HostCtrl2);
gBS->Stall (5000);
if (EFI_ERROR (Status)) {
return Status;
}
}
return Status; return Status;
} }
@ -1082,6 +1094,7 @@ SdMmcHcInitHost (
EFI_STATUS Status; EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_IO_PROTOCOL *PciIo;
SD_MMC_HC_SLOT_CAP Capability; SD_MMC_HC_SLOT_CAP Capability;
UINT32 value32;
// //
// Notify the SD/MMC override protocol that we are about to initialize // Notify the SD/MMC override protocol that we are about to initialize
@ -1104,15 +1117,200 @@ SdMmcHcInitHost (
PciIo = Private->PciIo; PciIo = Private->PciIo;
Capability = Private->Capability[Slot]; Capability = Private->Capability[Slot];
if (BhtHostPciSupport(PciIo)){
UINT8 CardMode;
UINT16 EmmcVar;
UINTN EmmcVarSize;
UINT64 Cap;
DbgMsg("find bht emmc chip\n");
//unlock PCR write protect
#ifdef DISABLE_L1_2
PciBhtAnd32(PciIo, 0xd0, ~(BIT31));
PciBhtAnd32(PciIo, 0x90, ~(BIT1 | BIT0));
value32 = PciBhtRead32(PciIo, 0xe0);
value32 &= ~(BIT31 | BIT30 | BIT29 | BIT28);
value32 |= (BIT29 | BIT28);
PciBhtWrite32(PciIo, 0xe0, value32);
value32 = PciBhtRead32(PciIo, 0xfc);
value32 &= ~(BIT19 | BIT18 | BIT17 | BIT16);
value32 |= (BIT19);
PciBhtWrite32(PciIo, 0xfc, value32);
value32 = PciBhtRead32(PciIo, 0x3f4);
value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0);
value32 |= (BIT3 | BIT1);
PciBhtWrite32(PciIo, 0x3f4, value32);
value32 = PciBhtRead32(PciIo, 0x248);
value32 &= ~(BIT3 | BIT2 | BIT1 | BIT0);
value32 |= (BIT3 | BIT1);
PciBhtWrite32(PciIo, 0x248, value32);
value32 = PciBhtRead32(PciIo, 0x90);
value32 &= ~(BIT1 | BIT0);
value32 |= (BIT1);
PciBhtWrite32(PciIo, 0x90, value32);
#endif
/* FET on */
PciBhtOr32(PciIo, 0xEC, 0x3);
/* Led on */
//PciBhtAnd32(PciIo, 0x334, (UINT32)~BIT13);
PciBhtOr32(PciIo, 0xD4, BIT6);
/* Set 1.8v emmc signaling flag */
PciBhtOr32(PciIo, 0x308, BIT4);
/* Set 200MBaseClock */
value32 = PciBhtRead32(PciIo, 0x304);
value32 &= 0x0000FFFF;
value32 |= 0x25100000;
#if !defined(HOST_CLK_DRIVE_STRENGTH) || HOST_CLK_DRIVE_STRENGTH > 7 || HOST_CLK_DRIVE_STRENGTH < 0
#error "HOST_CMD_DRIVE_STRENGTH is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_CLK_DRIVER_STRENGTH",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status))
EmmcVar = HOST_CLK_DRIVE_STRENGTH;
value32 &= 0xFFFFFF8F;
value32 |= ((EmmcVar & 0x7) << 4);
#endif
#if !defined(HOST_DAT_DRIVE_STRENGTH) || HOST_DAT_DRIVE_STRENGTH > 7 || HOST_DAT_DRIVE_STRENGTH < 0
#error "HOST_DATA_DRIVE_STRENGTH is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_DATA_DRIVER_STRENGTH",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status))
EmmcVar = HOST_DAT_DRIVE_STRENGTH;
value32 &= 0xFFFFFFF1;
value32 |= ((EmmcVar & 0x7) << 1);
#endif
PciBhtWrite32(PciIo, 0x304, value32);
PciBhtOr32(PciIo, 0x3E4, BIT22);
EmmcVarSize = sizeof(CardMode);
Status = gRT->GetVariable (
L"EMMC_FORCE_CARD_MODE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&CardMode
);
if (EFI_ERROR(Status) || CardMode > 2) {
CardMode = 0;
}
if (CardMode == 1) {
#if !defined(HS100_ALLPASS_PHASE) || HS100_ALLPASS_PHASE > 10 || HS100_ALLPASS_PHASE < 0
#error "HS200_ALLPASS_PHASE is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS100_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS100_ALLPASS_PHASE;
#endif
} else if (CardMode == 2) {
#if !defined(HS200_ALLPASS_PHASE) || HS200_ALLPASS_PHASE > 10 || HS200_ALLPASS_PHASE < 0
#error "HS200_ALLPASS_PHASE is undefined or value is invalid"
#else
EmmcVarSize = sizeof(EmmcVar);
Status = gRT->GetVariable (
L"EMMC_HS200_ALLPASS_PHASE",
&gEfiGenericVariableGuid,
NULL,
&EmmcVarSize,
&EmmcVar
);
if (EFI_ERROR(Status) || EmmcVar > 10)
EmmcVar = HS200_ALLPASS_PHASE;
}
#endif
value32 = 0x21000033 | (EmmcVar << 20);
PciBhtWrite32(PciIo, 0x300, value32);
//enable internal clk
value32 = BIT0;
Status = SdMmcHcOrMmio (PciIo, Slot, SD_MMC_HC_CLOCK_CTRL,sizeof(value32), &value32);
//reset pll start
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
value32 |= BIT12;
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
gBS->Stall(1);
//reset pll end
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE,sizeof(value32), &value32);
value32 &= ~BIT12;
value32 |= BIT18;
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
//wait BaseClk stable 0x1CC bit14
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
while(!(value32&BIT14)){
gBS->Stall(100);
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
DbgMsg("1CC=0x%08x\n", value32);
}
if (value32 & BIT18)
{
//Wait 2nd Card Detect debounce Finished by wait twice of debounce max time
while (1) {
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_PRESENT_STATE, TRUE, sizeof(value32), &value32);
if (((value32 >> 16) & 0x01) == ((value32 >> 18) & 0x01))
break;
}
//force pll active end
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, TRUE, sizeof(value32), &value32);
value32 &= ~BIT18;
Status = SdMmcHcRwMmio (PciIo, Slot, 0x1CC, FALSE, sizeof(value32), &value32);
}
Status = SdMmcHcRwMmio (PciIo, Slot, SD_MMC_HC_CAP, TRUE, sizeof (Cap), &Cap);
if (EFI_ERROR (Status)) {
return Status;
}
CopyMem (&Capability, &Cap, sizeof (Cap));
Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
if (EFI_ERROR (Status)) {
DbgMsg("emmc host init failure\n");
return Status;
}
}
Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]); Status = SdMmcHcInitClockFreq (PciIo, Slot, Private->BaseClkFreq[Slot]);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
if (!BhtHostPciSupport(PciIo)){
Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability); Status = SdMmcHcInitPowerVoltage (PciIo, Slot, Capability);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
} }
}
Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot); Status = SdMmcHcInitTimeoutCtrl (PciIo, Slot);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -2096,3 +2294,280 @@ SdMmcWaitTrbResult (
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
BOOLEAN BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo)
{
PCI_TYPE00 Pci;
PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32,
0, sizeof Pci / sizeof (UINT32), &Pci);
DEBUG ((DEBUG_INFO, "check device %04x:%04x\n", Pci.Hdr.VendorId, Pci.Hdr.DeviceId));
if (Pci.Hdr.VendorId != 0x1217)
goto end;
switch (Pci.Hdr.DeviceId)
{
case 0x8420: //PCI_DEV_ID_SDS0
case 0x8421: //PCI_DEV_ID_SDS1
case 0x8520: //PCI_DEV_ID_FJ2
case 0x8620: //PCI_DEV_ID_SB0
case 0x8621: //PCI_DEV_ID_SB1
g_deviceId = Pci.Hdr.DeviceId;
return 1;
default:
break;
}
end:
return 0;
}
void DbgNull(IN CONST CHAR16 * fmt, ...)
{
}
UINT32 bht_readl(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
{
UINT32 arg;
PciIo->Mem.Read(PciIo,EfiPciIoWidthUint32,1,offset,1,&arg);
return arg;
}
void bht_writel(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
{
PciIo->Mem.Write(PciIo,EfiPciIoWidthUint32,1,offset,1,&value);
}
UINT32 PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset)
{
UINT32 i = 0;
UINT32 tmp[3] = {0};
if((g_deviceId == PCI_DEV_ID_SDS0) ||
(g_deviceId == PCI_DEV_ID_SDS1) ||
(g_deviceId == PCI_DEV_ID_FJ2) ||
(g_deviceId == PCI_DEV_ID_SB0) ||
(g_deviceId == PCI_DEV_ID_SB1))
{
// For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
// Enable mapping
// Check function conflict
if((g_deviceId == PCI_DEV_ID_SDS0) ||
(g_deviceId == PCI_DEV_ID_FJ2) ||
(g_deviceId == PCI_DEV_ID_SB0) ||
(g_deviceId == PCI_DEV_ID_SB1))
{
i = 0;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
{
if(i == 5)
{
//DbgMsg((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
goto RD_DIS_MAPPING;
}
gBS->Stall(1000);
i++;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
}
}
else if(g_deviceId == PCI_DEV_ID_SDS1)
{
i = 0;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() function 1 can't lock!\n", __FUNCTION__));
goto RD_DIS_MAPPING;
}
gBS->Stall(1000);
i++;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
}
}
// Check last operation is complete
i = 0;
while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - [204] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingCtl)));
//DbgErr((DRIVERNAME " - [208] = 0x%x\n", RegisterRead32(ELN_dPCIRMappingEn)));
//DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
goto RD_DIS_MAPPING;
}
gBS->Stall(1000);
i += 1;
}
// Set register address
tmp[0] |= 0x40000000;
tmp[0] |= offset;
bht_writel(PciIo, BHT_PCIRMappingCtl, tmp[0]);
// Check read is complete
i = 0;
while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x40000000)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() check read operation complete timeout!!!\n", __FUNCTION__));
goto RD_DIS_MAPPING;
}
gBS->Stall(1000);
i += 1;
}
// Get PCIR value
tmp[1] = bht_readl(PciIo, BHT_PCIRMappingVal);
RD_DIS_MAPPING:
// Disable mapping
bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
//DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[1]);
return tmp[1];
}
//DbgDebug(L"%s offset=%x Value:%x\n", __FUNCTION__, offset, tmp[0]);
return tmp[0];
}
void PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
{
UINT32 tmp = 0;
UINT32 i = 0;
if((g_deviceId == PCI_DEV_ID_SDS0) ||
(g_deviceId == PCI_DEV_ID_SDS1) ||
(g_deviceId == PCI_DEV_ID_FJ2) ||
(g_deviceId == PCI_DEV_ID_SB0) ||
(g_deviceId == PCI_DEV_ID_SB1))
{
// For Sandstorm, HW implement a mapping method by memory space reg to access PCI reg.
// Upper caller doesn't need to set 0xD0.
// Enable mapping
// Check function conflict
if((g_deviceId == PCI_DEV_ID_SDS0) ||
(g_deviceId == PCI_DEV_ID_FJ2) ||
(g_deviceId == PCI_DEV_ID_SB0) ||
(g_deviceId == PCI_DEV_ID_SB1))
{
i = 0;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x40000000) == 0)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
goto WR_DIS_MAPPING;
}
gBS->Stall(1000);
i++;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x40000000);
}
}
else if(g_deviceId == PCI_DEV_ID_SDS1)
{
i = 0;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
while((bht_readl(PciIo, BHT_PCIRMappingEn) & 0x20000000) == 0)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() function 0 can't lock!\n", __FUNCTION__));
goto WR_DIS_MAPPING;
}
gBS->Stall(1000);
i++;
bht_writel(PciIo, BHT_PCIRMappingEn, 0x20000000);
}
}
// Enable MEM access
bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000000);
bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
// Check last operation is complete
i = 0;
while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
goto WR_DIS_MAPPING;
}
gBS->Stall(1000);
i += 1;
}
// Set write value
bht_writel(PciIo, BHT_PCIRMappingVal, value);
// Set register address
tmp |= 0x80000000;
tmp |= offset;
bht_writel(PciIo, BHT_PCIRMappingCtl, tmp);
// Check write is complete
i = 0;
while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0x80000000)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() check write operation complete timeout!!!\n", __FUNCTION__));
goto WR_DIS_MAPPING;
}
gBS->Stall(1000);
i += 1;
}
WR_DIS_MAPPING:
// Disable MEM access
bht_writel(PciIo, BHT_PCIRMappingVal, 0x80000001);
bht_writel(PciIo, BHT_PCIRMappingCtl, 0x800000D0);
// Check last operation is complete
i = 0;
while(bht_readl(PciIo, BHT_PCIRMappingCtl) & 0xc0000000)
{
if(i == 5)
{
//DbgErr((DRIVERNAME " - %s() check last operation complete timeout!!!\n", __FUNCTION__));
break;
}
gBS->Stall(1000);
i += 1;
}
// Disable function conflict
// Disable mapping
bht_writel(PciIo, BHT_PCIRMappingEn, 0x80000000);
}
}
void PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
{
UINT32 arg;
arg = PciBhtRead32(PciIo, offset);
PciBhtWrite32(PciIo, offset, value | arg);
}
void PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value)
{
UINT32 arg;
arg = PciBhtRead32(PciIo, offset);
PciBhtWrite32(PciIo, offset, value & arg);
}

View File

@ -552,4 +552,42 @@ SdMmcHcUhsSignaling (
IN SD_MMC_BUS_MODE Timing IN SD_MMC_BUS_MODE Timing
); );
BOOLEAN
BhtHostPciSupport(EFI_PCI_IO_PROTOCOL *PciIo);
UINT32
PciBhtRead32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset);
void
PciBhtWrite32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
void
PciBhtOr32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
void
PciBhtAnd32(EFI_PCI_IO_PROTOCOL *PciIo, UINT32 offset, UINT32 value);
extern void
DbgNull(IN CONST CHAR16 * fmt, ...);
#if(0)
#define DbgMsg(arg, ...) Print(L##arg, __VA_ARGS__)
#else
#define DbgMsg(...) DEBUG((DEBUG_INFO, __VA_ARGS__))
#endif
#define PCI_DEV_ID_RJ 0x8320
#define PCI_DEV_ID_SDS0 0x8420
#define PCI_DEV_ID_SDS1 0x8421
#define PCI_DEV_ID_FJ2 0x8520
#define PCI_DEV_ID_SB0 0x8620
#define PCI_DEV_ID_SB1 0x8621
// O2/BHT add BAR1 for PCIR mapping registers
// These registers is defined by O2/BHT, but we may follow name definition rule.
#define BHT_PCIRMappingVal (0x200) /* PCI CFG Space Register Mapping Value Register */
#define BHT_PCIRMappingCtl (0x204) /* PCI CFG Space Register Mapping Control Register */
#define BHT_PCIRMappingEn (0x208) /* PCI CFG Space Register Mapping Enable Register */
#define BHT_GPIOCTL (0x210) /* GPIO control register*/
#endif #endif

View File

@ -221,7 +221,7 @@ USBKeyboardDriverBindingStart (
EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints; EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
// //
// Traverse endpoints to find interrupt endpoint // Traverse endpoints to find interrupt endpoint IN
// //
Found = FALSE; Found = FALSE;
for (Index = 0; Index < EndpointNumber; Index++) { for (Index = 0; Index < EndpointNumber; Index++) {
@ -232,7 +232,8 @@ USBKeyboardDriverBindingStart (
&EndpointDescriptor &EndpointDescriptor
); );
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT &&
(EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) ) {
// //
// We only care interrupt endpoint here // We only care interrupt endpoint here
// //

View File

@ -793,6 +793,29 @@ InitKeyboardLayout (
} }
/**
Determine if SetIdle request is needed
@param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance.
@retval TRUE The USB device requires SetIdle to be called.
@retval FALSE The USB device does not require SetIdle to be called.
**/
BOOLEAN
UsbQuirkRequireSetIdle (
IN EFI_USB_DEVICE_DESCRIPTOR DevDesc
)
{
switch (DevDesc.IdVendor) {
case 0x0557:
return DevDesc.IdProduct == 0x2419;
default:
return FALSE;
}
}
/** /**
Initialize USB keyboard device and all private data structures. Initialize USB keyboard device and all private data structures.
@ -807,10 +830,8 @@ InitUSBKeyboard (
IN OUT USB_KB_DEV *UsbKeyboardDevice IN OUT USB_KB_DEV *UsbKeyboardDevice
) )
{ {
UINT16 ConfigValue;
UINT8 Protocol;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 TransferResult; EFI_USB_DEVICE_DESCRIPTOR DevDesc;
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( REPORT_STATUS_CODE_WITH_DEVICE_PATH (
EFI_PROGRESS_CODE, EFI_PROGRESS_CODE,
@ -823,27 +844,28 @@ InitUSBKeyboard (
InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA)); InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));
// //
// Use the config out of the descriptor // Get device descriptor so vendor/device IDs available
// Assumed the first config is the correct one and this is not always the case // for quirk handling
// //
Status = UsbGetConfiguration ( Status = UsbKeyboardDevice->UsbIo->UsbGetDeviceDescriptor (
UsbKeyboardDevice->UsbIo, UsbKeyboardDevice->UsbIo,
&ConfigValue, &DevDesc);
&TransferResult
);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
ConfigValue = 0x01; return EFI_DEVICE_ERROR;
}
// //
// Uses default configuration to configure the USB Keyboard device. // Set boot protocol for the USB Keyboard.
// This driver only supports boot protocol.
// //
Status = UsbSetConfiguration ( Status = UsbSetProtocolRequest (
UsbKeyboardDevice->UsbIo, UsbKeyboardDevice->UsbIo,
ConfigValue, UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
&TransferResult BOOT_PROTOCOL
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
// //
// If configuration could not be set here, it means // If protocol could not be set here, it means
// the keyboard interface has some errors and could // the keyboard interface has some errors and could
// not be initialized // not be initialized
// //
@ -855,24 +877,6 @@ InitUSBKeyboard (
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
}
UsbGetProtocolRequest (
UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
&Protocol
);
//
// Set boot protocol for the USB Keyboard.
// This driver only supports boot protocol.
//
if (Protocol != BOOT_PROTOCOL) {
UsbSetProtocolRequest (
UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
BOOT_PROTOCOL
);
}
UsbKeyboardDevice->CtrlOn = FALSE; UsbKeyboardDevice->CtrlOn = FALSE;
UsbKeyboardDevice->AltOn = FALSE; UsbKeyboardDevice->AltOn = FALSE;
@ -896,6 +900,16 @@ InitUSBKeyboard (
UsbKeyboardDevice->CurrentNsKey = NULL; UsbKeyboardDevice->CurrentNsKey = NULL;
//
// Some keyboards don't send interrupt transfers until SetIdle is called
//
if (UsbQuirkRequireSetIdle(DevDesc)) {
UsbSetIdleRequest(UsbKeyboardDevice->UsbIo,
UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
0,
0);
}
// //
// Sync the initial state of lights on keyboard. // Sync the initial state of lights on keyboard.
// //

View File

@ -329,4 +329,18 @@ InitializeKeyState (
OUT EFI_KEY_STATE *KeyState OUT EFI_KEY_STATE *KeyState
); );
/**
Determine if SetIdle request is needed
@param DevDesc The EFI_USB_DEVICE_DESCRIPTOR instance.
@retval TRUE The USB device requires SetIdle to be called.
@retval FALSE The USB device does not require SetIdle to be called.
**/
BOOLEAN
UsbQuirkRequireSetIdle (
IN EFI_USB_DEVICE_DESCRIPTOR DevDesc
);
#endif #endif

View File

@ -209,7 +209,7 @@ USBMouseDriverBindingStart (
EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints; EndpointNumber = UsbMouseDevice->InterfaceDescriptor.NumEndpoints;
// //
// Traverse endpoints to find interrupt endpoint // Traverse endpoints to find interrupt endpoint IN
// //
Found = FALSE; Found = FALSE;
for (Index = 0; Index < EndpointNumber; Index++) { for (Index = 0; Index < EndpointNumber; Index++) {
@ -219,7 +219,8 @@ USBMouseDriverBindingStart (
&EndpointDescriptor &EndpointDescriptor
); );
if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) { if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT &&
(EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) ) {
// //
// We only care interrupt endpoint here // We only care interrupt endpoint here
// //

View File

@ -44,8 +44,8 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
// //
PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = { PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
PartitionInstallGptChildHandles, PartitionInstallGptChildHandles,
PartitionInstallMbrChildHandles,
PartitionInstallUdfChildHandles, PartitionInstallUdfChildHandles,
PartitionInstallMbrChildHandles,
NULL NULL
}; };

View File

@ -944,6 +944,8 @@ UpdateVariable (
UINTN VarSize; UINTN VarSize;
VARIABLE_GLOBAL *Global; VARIABLE_GLOBAL *Global;
UINTN NonVolatileVarableStoreSize; UINTN NonVolatileVarableStoreSize;
UINT32 Result;
BOOLEAN Delete = FALSE;
Global = &mVariableModuleGlobal->VariableGlobal[Physical]; Global = &mVariableModuleGlobal->VariableGlobal[Physical];
@ -976,10 +978,8 @@ UpdateVariable (
// specified causes it to be deleted. // specified causes it to be deleted.
// //
if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) { if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {
Variable->CurrPtr->State &= VAR_DELETED; DataSize = 0;
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE); Delete = TRUE;
Status = EFI_SUCCESS;
goto Done;
} }
// //
@ -989,8 +989,12 @@ UpdateVariable (
if (Variable->CurrPtr->DataSize == DataSize && if (Variable->CurrPtr->DataSize == DataSize &&
CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0 CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0
) { ) {
if (Delete) {
goto Update;
} else {
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
goto Done; goto Done;
}
} else if (Variable->CurrPtr->State == VAR_ADDED) { } else if (Variable->CurrPtr->State == VAR_ADDED) {
// //
// Mark the old variable as in delete transition // Mark the old variable as in delete transition
@ -1032,6 +1036,10 @@ UpdateVariable (
VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize); VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);
VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize); VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize);
if (Delete) {
goto Store;
}
if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) { if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(Global->NonVolatileVariableBase))->Size; NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(Global->NonVolatileVariableBase))->Size;
if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
@ -1089,7 +1097,17 @@ UpdateVariable (
DataSize DataSize
); );
if (storeInitialized && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) { Store:
// If the store is initialized
// And we are storing or deleting a non volatile variable
// And variable name starts with 'Boot'
// Send the new data to SMMSTORE
if (storeInitialized && (
(Attributes & EFI_VARIABLE_NON_VOLATILE) != 0 || (
Delete &&
(Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0
)) && (!StrnCmp(L"Boot", VariableName, StrLen(L"Boot")))
) {
/* TODO: add hook for logging nv changes here */ /* TODO: add hook for logging nv changes here */
@ -1108,7 +1126,10 @@ UpdateVariable (
CopyMem (keydata + sizeof (EFI_GUID), VariableName, VarNameSize); CopyMem (keydata + sizeof (EFI_GUID), VariableName, VarNameSize);
CopyMem (valdata, Data, DataSize); CopyMem (valdata, Data, DataSize);
call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_APPEND, (UINT32)rt_buffer_phys); Result = call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_APPEND, (UINT32)rt_buffer_phys);
if (Result != SMMSTORE_RET_SUCCESS) {
return EFI_DEVICE_ERROR;
}
/* call into SMM through EFI_ISA_IO_PROTOCOL to write to 0xb2: /* call into SMM through EFI_ISA_IO_PROTOCOL to write to 0xb2:
* set registers (how?) * set registers (how?)
* UINT8 Data = ...; * UINT8 Data = ...;
@ -1116,6 +1137,7 @@ UpdateVariable (
*/ */
} }
Update:
// //
// Mark the old variable as deleted // Mark the old variable as deleted
// //
@ -1123,7 +1145,11 @@ UpdateVariable (
Variable->CurrPtr->State &= VAR_DELETED; Variable->CurrPtr->State &= VAR_DELETED;
} }
if (Delete) {
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
} else {
UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE); UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
}
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
@ -1875,7 +1901,7 @@ VariableCommonInitialize (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Result;
// //
// Allocate memory for mVariableModuleGlobal // Allocate memory for mVariableModuleGlobal
// //
@ -1928,14 +1954,18 @@ VariableCommonInitialize (
.bufsize = sizeof(buf), .bufsize = sizeof(buf),
}; };
ASSERT((UINTN)&read_cmd <= 0x100000000 - sizeof(read_cmd)); ASSERT((UINTN)&read_cmd <= 0x100000000 - sizeof(read_cmd));
call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_READ, (UINT32)(UINTN)&read_cmd); Result = call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_READ, (UINT32)(UINTN)&read_cmd);
if (Result != SMMSTORE_RET_SUCCESS) {
// The SMM store hasn't been compiled in. There's nothing we can do.
return EFI_SUCCESS;
}
DEBUG ((DEBUG_WARN, "Initialize buffer from 0x%x bytes of flash\n", read_cmd.bufsize)); DEBUG ((DEBUG_WARN, "Initialize buffer from 0x%x bytes of flash\n", read_cmd.bufsize));
int i = 0; int i = 0;
while (i < read_cmd.bufsize) { while (i < read_cmd.bufsize) {
// assume native endian // assume native endian
UINT32 keysz = ((UINT32 *)(buf + i))[0]; UINT32 keysz = ((UINT32 *)(buf + i))[0];
if (keysz == 0xffffffff) if (keysz == 0 || keysz == 0xffffffff)
break; // no more entries break; // no more entries
UINTN valsz = ((UINT32 *)(buf + i))[1]; UINTN valsz = ((UINT32 *)(buf + i))[1];
@ -1949,6 +1979,8 @@ VariableCommonInitialize (
EFI_GUID *guid = (EFI_GUID *)(buf + i + 8); EFI_GUID *guid = (EFI_GUID *)(buf + i + 8);
VOID *data = (VOID *)(buf + i + 8 + keysz); VOID *data = (VOID *)(buf + i + 8 + keysz);
// only update Boot* variables
if (!StrnCmp(L"Boot", varname, StrLen(L"Boot"))) {
DEBUG ((DEBUG_WARN, "Fetching variable: %s\n", varname)); DEBUG ((DEBUG_WARN, "Fetching variable: %s\n", varname));
DEBUG ((DEBUG_WARN, "buf: %p, buf+i: %p, guid: %p, varname: %p, data: %p\n", buf, buf + i, guid, varname, data)); DEBUG ((DEBUG_WARN, "buf: %p, buf+i: %p, guid: %p, varname: %p, data: %p\n", buf, buf + i, guid, varname, data));
VARIABLE_POINTER_TRACK Variable; VARIABLE_POINTER_TRACK Variable;
@ -1964,8 +1996,10 @@ VariableCommonInitialize (
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
&Variable &Variable
); );
} else {
DEBUG ((DEBUG_WARN, "Skipping non-Boot variable: %s\n", varname));
}
} }
DEBUG ((DEBUG_WARN, "Added variable: 0x%x, val size: %x\n", keysz, valsz));
// no UEFI variable since it's at most the GUID part, so skip // no UEFI variable since it's at most the GUID part, so skip
i += 8 + keysz + valsz + 1; i += 8 + keysz + valsz + 1;
i = (i + 3) & ~3; i = (i + 3) & ~3;