Skip to content

Commit

Permalink
Platform/RPi: Make 3GB/4GB a runtime (BIOS setup) choice
Browse files Browse the repository at this point in the history
Currently some OSes (e.g FreeBSD) can make full use of the maximum
4 GB of RAM a Raspberry Pi 4 can offer, whereas others (e.g. Linux)
must be restricted to only the first 3 GB.

Previously this was a compile-time choice chosen by PcdAcpiBasicMode,
and now we make it user-selectable. The default is a 3 GB limit.

Signed-off-by: Pete Batard <pete@akeo.ie>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
  • Loading branch information
andreiw authored and Ard Biesheuvel committed Mar 3, 2020
1 parent 4fb9158 commit 874750a
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 14 deletions.
72 changes: 62 additions & 10 deletions Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
#include <Library/AcpiLib.h>
#include <Library/HiiLib.h>
#include <Library/DebugLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/IoLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <IndustryStandard/RpiMbox.h>
#include <IndustryStandard/Bcm2711.h>
#include <IndustryStandard/Bcm2836.h>
#include <IndustryStandard/Bcm2836Gpio.h>
#include <Library/GpioLib.h>
Expand All @@ -26,6 +28,8 @@ extern UINT8 ConfigDxeHiiBin[];
extern UINT8 ConfigDxeStrings[];

STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
STATIC UINT32 mModelFamily = 0;
STATIC UINT32 mModelInstalledMB = 0;

/*
* The GUID inside Platform/RaspberryPi/RPi3/AcpiTables/AcpiTables.inf and
Expand Down Expand Up @@ -129,6 +133,24 @@ SetupVariables (
PcdSet32 (PcdCustomCpuClock, PcdGet32 (PcdCustomCpuClock));
}

if (mModelFamily >= 4 && mModelInstalledMB > 3 * 1024) {
/*
* This allows changing PcdRamLimitTo3GB in forms.
*/
PcdSet32 (PcdRamMoreThan3GB, 1);

Size = sizeof (UINT32);
Status = gRT->GetVariable (L"RamLimitTo3GB",
&gConfigDxeFormSetGuid,
NULL, &Size, &Var32);
if (EFI_ERROR (Status)) {
PcdSet32 (PcdRamLimitTo3GB, PcdGet32 (PcdRamLimitTo3GB));
}
} else {
PcdSet32 (PcdRamMoreThan3GB, 0);
PcdSet32 (PcdRamLimitTo3GB, 0);
}

Size = sizeof (UINT32);
Status = gRT->GetVariable (L"SdIsArasan",
&gConfigDxeFormSetGuid,
Expand Down Expand Up @@ -224,7 +246,7 @@ ApplyVariables (
UINT32 CpuClock = PcdGet32 (PcdCpuClock);
UINT32 CustomCpuClock = PcdGet32 (PcdCustomCpuClock);
UINT32 Rate = 0;
UINT32 ModelFamily = 0;
UINT64 SystemMemorySize;

if (CpuClock != 0) {
if (CpuClock == 2) {
Expand Down Expand Up @@ -258,15 +280,31 @@ ApplyVariables (
DEBUG ((DEBUG_INFO, "Current CPU speed is %uHz\n", Rate));
}

Status = mFwProtocol->GetModelFamily (&ModelFamily);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi model family: %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "Current Raspberry Pi model family is 0x%x\n", ModelFamily));
}
if (mModelFamily >= 4 && PcdGet32 (PcdRamLimitTo3GB) == 0) {
/*
* Similar to how we compute the > 3 GB RAM segment's size in PlatformLib/
* RaspberryPiMem.c, with some overlap protection for the Bcm2xxx register
* spaces. This computation should also work for models with more than 4 GB
* RAM, if there ever exist ones.
*/
SystemMemorySize = (UINT64)mModelInstalledMB * SIZE_1MB;
ASSERT (SystemMemorySize > 3UL * SIZE_1GB);
SystemMemorySize = MIN(SystemMemorySize, BCM2836_SOC_REGISTERS);
if (BCM2711_SOC_REGISTERS > 0) {
SystemMemorySize = MIN(SystemMemorySize, BCM2711_SOC_REGISTERS);
}

Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, 3UL * BASE_1GB,
SystemMemorySize - (3UL * SIZE_1GB),
EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB);
ASSERT_EFI_ERROR (Status);
Status = gDS->SetMemorySpaceAttributes (3UL * BASE_1GB,
SystemMemorySize - (3UL * SIZE_1GB),
EFI_MEMORY_WB);
ASSERT_EFI_ERROR (Status);
}

if (ModelFamily == 3) {
if (mModelFamily == 3) {
/*
* Pi 3: either Arasan or SdHost goes to SD card.
*
Expand Down Expand Up @@ -316,7 +354,7 @@ ApplyVariables (
GpioPinFuncSet (52, Gpio48Group);
GpioPinFuncSet (53, Gpio48Group);

} else if (ModelFamily == 4) {
} else if (mModelFamily == 4) {
/*
* Pi 4: either Arasan or eMMC2 goes to SD card.
*/
Expand Down Expand Up @@ -352,7 +390,7 @@ ApplyVariables (
GpioPinFuncSet (39, GPIO_FSEL_ALT3);
}
} else {
DEBUG ((DEBUG_ERROR, "Model Family %d not supported...\n", ModelFamily));
DEBUG ((DEBUG_ERROR, "Model Family %d not supported...\n", mModelFamily));
}

/*
Expand Down Expand Up @@ -400,6 +438,20 @@ ConfigInitialize (
return Status;
}

Status = mFwProtocol->GetModelFamily (&mModelFamily);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi model family: %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "Current Raspberry Pi model family is %d\n", mModelFamily));
}

Status = mFwProtocol->GetModelInstalledMB (&mModelInstalledMB);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi installed RAM size: %r\n", Status));
} else {
DEBUG ((DEBUG_INFO, "Current Raspberry Pi installed RAM size is %d MB\n", mModelInstalledMB));
}

Status = SetupVariables ();
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_ERROR, "Couldn't not setup NV vars: %r\n", Status));
Expand Down
8 changes: 5 additions & 3 deletions Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxe.inf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
ArmPlatformPkg/ArmPlatformPkg.dec
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
Silicon/Broadcom/Bcm27xx/Bcm27xx.dec
Silicon/Broadcom/Bcm283x/Bcm283x.dec
Platform/RaspberryPi/RaspberryPi.dec
EmbeddedPkg/EmbeddedPkg.dec
Expand All @@ -53,10 +54,11 @@
gConfigDxeFormSetGuid

[Protocols]
gRaspberryPiFirmwareProtocolGuid ## CONSUMES
gRaspberryPiFirmwareProtocolGuid ## CONSUMES
gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES

[Pcd]
gBcm27xxTokenSpaceGuid.PcdBcm27xxRegistersAddress
gBcm283xTokenSpaceGuid.PcdBcm283xRegistersAddress
gRaspberryPiTokenSpaceGuid.PcdCpuClock
gRaspberryPiTokenSpaceGuid.PcdCustomCpuClock
Expand All @@ -70,8 +72,8 @@
gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableScaledVModes
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot

[FeaturePcd]
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB

[Depex]
gPcdProtocolGuid AND gRaspberryPiFirmwareProtocolGuid
11 changes: 11 additions & 0 deletions Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.uni
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@
#string STR_CHIPSET_SD_SDHOST #language en-US "Broadcom SDHOST"
#string STR_CHIPSET_SD_ARASAN #language en-US "Arasan SDHCI"

/*
* Advanced configuration.
*/

#string STR_ADVANCED_FORM_TITLE #language en-US "Advanced Configuration"

#string STR_ADVANCED_3GB_PROMPT #language en-US "Limit RAM to 3 GB"
#string STR_ADVANCED_3GB_HELP #language en-US "OSes not supporting ACPI DMA constraints require a 3 GB limit or face broken xHCI USB"
#string STR_ADVANCED_3GB_OFF #language en-US "Disabled"
#string STR_ADVANCED_3GB_ON #language en-US "Enabled"

/*
* MMC/SD configuration.
*/
Expand Down
41 changes: 41 additions & 0 deletions Platform/RaspberryPi/Drivers/ConfigDxe/ConfigDxeHii.vfr
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ typedef struct {
UINT32 Routing;
} CHIPSET_SD_VARSTORE_DATA;

typedef struct {
/*
* Always set by ConfigDxe prior to HII init to reflect
* platform capability.
*/
UINT32 Supported;
} ADVANCED_RAM_MORE_THAN_3GB_VARSTORE_DATA;

typedef struct {
UINT32 Enabled;
} ADVANCED_RAM_LIMIT_TO_3GB_VARSTORE_DATA;

typedef struct {
/*
* 0 - Don't disable multi-block.
Expand Down Expand Up @@ -140,6 +152,16 @@ formset
name = SdIsArasan,
guid = CONFIGDXE_FORM_SET_GUID;

efivarstore ADVANCED_RAM_MORE_THAN_3GB_VARSTORE_DATA,
attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
name = RamMoreThan3GB,
guid = CONFIGDXE_FORM_SET_GUID;

efivarstore ADVANCED_RAM_LIMIT_TO_3GB_VARSTORE_DATA,
attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
name = RamLimitTo3GB,
guid = CONFIGDXE_FORM_SET_GUID;

efivarstore MMC_DISMULTI_VARSTORE_DATA,
attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
name = MmcDisableMulti,
Expand Down Expand Up @@ -193,6 +215,10 @@ formset
prompt = STRING_TOKEN(STR_CHIPSET_FORM_TITLE),
help = STRING_TOKEN(STR_NULL_STRING);

goto 0x1006,
prompt = STRING_TOKEN(STR_ADVANCED_FORM_TITLE),
help = STRING_TOKEN(STR_NULL_STRING);

goto 0x1003,
prompt = STRING_TOKEN(STR_MMC_FORM_TITLE),
help = STRING_TOKEN(STR_NULL_STRING);
Expand Down Expand Up @@ -240,6 +266,21 @@ formset
endoneof;
endform;

form formid = 0x1006,
title = STRING_TOKEN(STR_ADVANCED_FORM_TITLE);
subtitle text = STRING_TOKEN(STR_NULL_STRING);

grayoutif ideqval RamMoreThan3GB.Supported == 0;
oneof varid = RamLimitTo3GB.Enabled,
prompt = STRING_TOKEN(STR_ADVANCED_3GB_PROMPT),
help = STRING_TOKEN(STR_ADVANCED_3GB_HELP),
flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED,
option text = STRING_TOKEN(STR_ADVANCED_3GB_OFF), value = 0, flags = DEFAULT;
option text = STRING_TOKEN(STR_ADVANCED_3GB_ON), value = 1, flags = 0;
endoneof;
endif;
endform;

form formid = 0x1003,
title = STRING_TOKEN(STR_MMC_FORM_TITLE);
subtitle text = STRING_TOKEN(STR_MMC_FORM_SUBTITLE);
Expand Down
6 changes: 6 additions & 0 deletions Platform/RaspberryPi/RPi3/RPi3.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,12 @@
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableScaledVModes|L"DisplayEnableScaledVModes"|gConfigDxeFormSetGuid|0x0|0xff
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot|L"DisplayEnableSShot"|gConfigDxeFormSetGuid|0x0|1

#
# Supporting > 3GB of memory.
#
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|L"RamMoreThan3GB"|gConfigDxeFormSetGuid|0x0|0
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|L"RamLimitTo3GB"|gConfigDxeFormSetGuid|0x0|0

#
# Common UEFI ones.
#
Expand Down
6 changes: 6 additions & 0 deletions Platform/RaspberryPi/RPi4/RPi4.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,12 @@
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableScaledVModes|L"DisplayEnableScaledVModes"|gConfigDxeFormSetGuid|0x0|0xff
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot|L"DisplayEnableSShot"|gConfigDxeFormSetGuid|0x0|1

#
# Supporting > 3GB of memory.
#
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|L"RamMoreThan3GB"|gConfigDxeFormSetGuid|0x0|0
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|L"RamLimitTo3GB"|gConfigDxeFormSetGuid|0x0|1

#
# Common UEFI ones.
#
Expand Down
4 changes: 3 additions & 1 deletion Platform/RaspberryPi/RaspberryPi.dec
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
gRaspberryPiTokenSpaceGuid.PcdCustomCpuClock|0|UINT32|0x00000016
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableScaledVModes|0|UINT8|0x00000017
gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot|0|UINT32|0x00000018
gRaspberryPiTokenSpaceGuid.PcdRamMoreThan3GB|0|UINT32|0x00000019
gRaspberryPiTokenSpaceGuid.PcdRamLimitTo3GB|0|UINT32|0x0000001A

[PcdsFeatureFlag.common]
gRaspberryPiTokenSpaceGuid.PcdAcpiBasicMode|FALSE|BOOLEAN|0x00000019
gRaspberryPiTokenSpaceGuid.PcdAcpiBasicMode|FALSE|BOOLEAN|0x0000001B

0 comments on commit 874750a

Please sign in to comment.