ConfigDxe.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /** @file
  2. *
  3. * Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
  4. * Copyright (c) 2018 - 2020, Andrei Warkentin <andrey.warkentin@gmail.com>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause-Patent
  7. *
  8. **/
  9. #include <Uefi.h>
  10. #include <IndustryStandard/Bcm2711.h>
  11. #include <IndustryStandard/Bcm2836.h>
  12. #include <IndustryStandard/Bcm2836Gpio.h>
  13. #include <IndustryStandard/RpiMbox.h>
  14. #include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
  15. #include <IndustryStandard/RpiDebugPort2Table.h>
  16. #include <UartSelection.h>
  17. #include <Library/AcpiLib.h>
  18. #include <Library/DebugLib.h>
  19. #include <Library/DevicePathLib.h>
  20. #include <Library/DxeServicesLib.h>
  21. #include <Library/DxeServicesTableLib.h>
  22. #include <Library/GpioLib.h>
  23. #include <Library/HiiLib.h>
  24. #include <Library/IoLib.h>
  25. #include <Library/NetLib.h>
  26. #include <Library/UefiBootServicesTableLib.h>
  27. #include <Library/UefiRuntimeServicesTableLib.h>
  28. #include <Library/PcdLib.h>
  29. #include <Protocol/AcpiTable.h>
  30. #include <Protocol/BcmGenetPlatformDevice.h>
  31. #include <Protocol/RpiFirmware.h>
  32. #include <ConfigVars.h>
  33. #include "ConfigDxeFormSetGuid.h"
  34. #include "ConfigDxe.h"
  35. #define FREQ_1_MHZ 1000000
  36. extern UINT8 ConfigDxeHiiBin[];
  37. extern UINT8 ConfigDxeStrings[];
  38. STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
  39. STATIC UINT32 mModelFamily = 0;
  40. STATIC UINT32 mModelInstalledMB = 0;
  41. STATIC UINT32 mModelRevision = 0;
  42. STATIC UINT32 mCoreClockRate = 0;
  43. STATIC EFI_MAC_ADDRESS mMacAddress;
  44. /*
  45. * The GUID inside Platform/RaspberryPi/RPi3/AcpiTables/AcpiTables.inf and
  46. * Platform/RaspberryPi/RPi4/AcpiTables/AcpiTables.inf _must_ match below.
  47. */
  48. STATIC CONST EFI_GUID mAcpiTableFile = {
  49. 0x7E374E25, 0x8E01, 0x4FEE, { 0x87, 0xf2, 0x39, 0x0C, 0x23, 0xC6, 0x06, 0xCD }
  50. };
  51. typedef struct {
  52. VENDOR_DEVICE_PATH VendorDevicePath;
  53. EFI_DEVICE_PATH_PROTOCOL End;
  54. } HII_VENDOR_DEVICE_PATH;
  55. #pragma pack (1)
  56. typedef struct {
  57. MAC_ADDR_DEVICE_PATH MacAddrDP;
  58. EFI_DEVICE_PATH_PROTOCOL End;
  59. } GENET_DEVICE_PATH;
  60. typedef struct {
  61. GENET_DEVICE_PATH DevicePath;
  62. BCM_GENET_PLATFORM_DEVICE_PROTOCOL PlatformDevice;
  63. } GENET_DEVICE;
  64. #pragma pack ()
  65. STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = {
  66. {
  67. {
  68. HARDWARE_DEVICE_PATH,
  69. HW_VENDOR_DP,
  70. {
  71. (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
  72. (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  73. }
  74. },
  75. CONFIGDXE_FORM_SET_GUID
  76. },
  77. {
  78. END_DEVICE_PATH_TYPE,
  79. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  80. {
  81. (UINT8)(END_DEVICE_PATH_LENGTH),
  82. (UINT8)((END_DEVICE_PATH_LENGTH) >> 8)
  83. }
  84. }
  85. };
  86. STATIC GENET_DEVICE mGenetDevice = {
  87. {
  88. {
  89. {
  90. MESSAGING_DEVICE_PATH,
  91. MSG_MAC_ADDR_DP,
  92. {
  93. (UINT8)(sizeof (MAC_ADDR_DEVICE_PATH)),
  94. (UINT8)((sizeof (MAC_ADDR_DEVICE_PATH)) >> 8)
  95. }
  96. },
  97. {{ 0 }},
  98. NET_IFTYPE_ETHERNET
  99. },
  100. {
  101. END_DEVICE_PATH_TYPE,
  102. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  103. {
  104. sizeof (EFI_DEVICE_PATH_PROTOCOL),
  105. 0
  106. }
  107. }
  108. },
  109. {
  110. GENET_BASE_ADDRESS,
  111. {{ 0 }}
  112. }
  113. };
  114. STATIC
  115. VOID
  116. EFIAPI
  117. RegisterDevices (
  118. EFI_EVENT Event,
  119. VOID *Context
  120. )
  121. {
  122. EFI_HANDLE Handle;
  123. EFI_STATUS Status;
  124. if (mModelFamily == 4) {
  125. DEBUG ((DEBUG_INFO, "GENET: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n",
  126. mMacAddress.Addr[0], mMacAddress.Addr[1], mMacAddress.Addr[2],
  127. mMacAddress.Addr[3], mMacAddress.Addr[4], mMacAddress.Addr[5]));
  128. CopyMem (&mGenetDevice.DevicePath.MacAddrDP.MacAddress, mMacAddress.Addr,
  129. NET_ETHER_ADDR_LEN);
  130. CopyMem (&mGenetDevice.PlatformDevice.MacAddress, mMacAddress.Addr,
  131. NET_ETHER_ADDR_LEN);
  132. Handle = NULL;
  133. Status = gBS->InstallMultipleProtocolInterfaces (&Handle,
  134. &gEfiDevicePathProtocolGuid, &mGenetDevice.DevicePath,
  135. &gBcmGenetPlatformDeviceProtocolGuid, &mGenetDevice.PlatformDevice,
  136. NULL);
  137. ASSERT_EFI_ERROR (Status);
  138. }
  139. }
  140. STATIC EFI_STATUS
  141. InstallHiiPages (
  142. VOID
  143. )
  144. {
  145. EFI_STATUS Status;
  146. EFI_HII_HANDLE HiiHandle;
  147. EFI_HANDLE DriverHandle;
  148. DriverHandle = NULL;
  149. Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle,
  150. &gEfiDevicePathProtocolGuid,
  151. &mVendorDevicePath,
  152. NULL);
  153. if (EFI_ERROR (Status)) {
  154. return Status;
  155. }
  156. HiiHandle = HiiAddPackages (&gConfigDxeFormSetGuid,
  157. DriverHandle,
  158. ConfigDxeStrings,
  159. ConfigDxeHiiBin,
  160. NULL);
  161. if (HiiHandle == NULL) {
  162. gBS->UninstallMultipleProtocolInterfaces (DriverHandle,
  163. &gEfiDevicePathProtocolGuid,
  164. &mVendorDevicePath,
  165. NULL);
  166. return EFI_OUT_OF_RESOURCES;
  167. }
  168. return EFI_SUCCESS;
  169. }
  170. STATIC EFI_STATUS
  171. SetupVariables (
  172. VOID
  173. )
  174. {
  175. UINTN Size;
  176. UINT8 Var8;
  177. UINT32 Var32;
  178. CHAR16 AssetTagVar[ASSET_TAG_STR_STORAGE_SIZE] = L"";
  179. EFI_STATUS Status;
  180. /*
  181. * Create the vars with default value.
  182. * If we don't, forms won't be able to update.
  183. */
  184. Size = sizeof (UINT32);
  185. Status = gRT->GetVariable (L"CpuClock",
  186. &gConfigDxeFormSetGuid,
  187. NULL, &Size, &Var32);
  188. if (EFI_ERROR (Status)) {
  189. Status = PcdSet32S (PcdCpuClock, PcdGet32 (PcdCpuClock));
  190. ASSERT_EFI_ERROR (Status);
  191. }
  192. Size = sizeof (UINT32);
  193. Status = gRT->GetVariable (L"CustomCpuClock",
  194. &gConfigDxeFormSetGuid,
  195. NULL, &Size, &Var32);
  196. if (EFI_ERROR (Status)) {
  197. Status = PcdSet32S (PcdCustomCpuClock, PcdGet32 (PcdCustomCpuClock));
  198. ASSERT_EFI_ERROR (Status);
  199. }
  200. if (mModelFamily >= 4 && mModelInstalledMB > 3 * 1024) {
  201. /*
  202. * This allows changing PcdRamLimitTo3GB in forms.
  203. */
  204. Status = PcdSet32S (PcdRamMoreThan3GB, 1);
  205. ASSERT_EFI_ERROR (Status);
  206. Size = sizeof (UINT32);
  207. Status = gRT->GetVariable (L"RamLimitTo3GB",
  208. &gConfigDxeFormSetGuid,
  209. NULL, &Size, &Var32);
  210. if (EFI_ERROR (Status)) {
  211. Status = PcdSet32S (PcdRamLimitTo3GB, PcdGet32 (PcdRamLimitTo3GB));
  212. ASSERT_EFI_ERROR (Status);
  213. }
  214. } else {
  215. Status = PcdSet32S (PcdRamMoreThan3GB, 0);
  216. ASSERT_EFI_ERROR (Status);
  217. Status = PcdSet32S (PcdRamLimitTo3GB, 0);
  218. ASSERT_EFI_ERROR (Status);
  219. }
  220. Size = sizeof (UINT32);
  221. Status = gRT->GetVariable (L"SystemTableMode",
  222. &gConfigDxeFormSetGuid,
  223. NULL, &Size, &Var32);
  224. if (EFI_ERROR (Status)) {
  225. Status = PcdSet32S (PcdSystemTableMode, PcdGet32 (PcdSystemTableMode));
  226. ASSERT_EFI_ERROR (Status);
  227. }
  228. Size = sizeof (UINT32);
  229. Status = gRT->GetVariable (L"FanOnGpio",
  230. &gConfigDxeFormSetGuid,
  231. NULL, &Size, &Var32);
  232. if (EFI_ERROR (Status)) {
  233. Status = PcdSet32S (PcdFanOnGpio, PcdGet32 (PcdFanOnGpio));
  234. ASSERT_EFI_ERROR (Status);
  235. }
  236. Size = sizeof (UINT32);
  237. Status = gRT->GetVariable (L"FanTemp",
  238. &gConfigDxeFormSetGuid,
  239. NULL, &Size, &Var32);
  240. if (EFI_ERROR (Status)) {
  241. Status = PcdSet32S (PcdFanTemp, PcdGet32 (PcdFanTemp));
  242. ASSERT_EFI_ERROR (Status);
  243. }
  244. if (mModelFamily >= 4) {
  245. if (((mModelRevision >> 4) & 0xFF) == 0x14) {
  246. /*
  247. * Enable PCIe by default on CM4
  248. */
  249. Status = PcdSet32S (PcdXhciPci, 2);
  250. ASSERT_EFI_ERROR (Status);
  251. } else {
  252. Size = sizeof (UINT32);
  253. Status = gRT->GetVariable (L"XhciPci",
  254. &gConfigDxeFormSetGuid,
  255. NULL, &Size, &Var32);
  256. if (EFI_ERROR (Status) || (Var32 == 0)) {
  257. /*
  258. * Enable XHCI by default
  259. */
  260. Status = PcdSet32S (PcdXhciPci, 0);
  261. ASSERT_EFI_ERROR (Status);
  262. } else {
  263. /*
  264. * Enable PCIe
  265. */
  266. Status = PcdSet32S (PcdXhciPci, 1);
  267. ASSERT_EFI_ERROR (Status);
  268. }
  269. }
  270. } else {
  271. /*
  272. * Disable PCIe and XHCI
  273. */
  274. Status = PcdSet32S (PcdXhciPci, 0);
  275. ASSERT_EFI_ERROR (Status);
  276. }
  277. Size = sizeof (AssetTagVar);
  278. Status = gRT->GetVariable (L"AssetTag",
  279. &gConfigDxeFormSetGuid,
  280. NULL, &Size, AssetTagVar);
  281. if (EFI_ERROR (Status)) {
  282. Status = gRT->SetVariable (
  283. L"AssetTag",
  284. &gConfigDxeFormSetGuid,
  285. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  286. sizeof (AssetTagVar),
  287. AssetTagVar
  288. );
  289. }
  290. Size = sizeof (UINT32);
  291. Status = gRT->GetVariable (L"SdIsArasan",
  292. &gConfigDxeFormSetGuid,
  293. NULL, &Size, &Var32);
  294. if (EFI_ERROR (Status)) {
  295. Status = PcdSet32S (PcdSdIsArasan, PcdGet32 (PcdSdIsArasan));
  296. ASSERT_EFI_ERROR (Status);
  297. }
  298. Size = sizeof (UINT32);
  299. Status = gRT->GetVariable (L"MmcDisableMulti",
  300. &gConfigDxeFormSetGuid,
  301. NULL, &Size, &Var32);
  302. if (EFI_ERROR (Status)) {
  303. Status = PcdSet32S (PcdMmcDisableMulti, PcdGet32 (PcdMmcDisableMulti));
  304. ASSERT_EFI_ERROR (Status);
  305. }
  306. Size = sizeof (UINT32);
  307. Status = gRT->GetVariable (L"MmcForce1Bit",
  308. &gConfigDxeFormSetGuid,
  309. NULL, &Size, &Var32);
  310. if (EFI_ERROR (Status)) {
  311. Status = PcdSet32S (PcdMmcForce1Bit, PcdGet32 (PcdMmcForce1Bit));
  312. ASSERT_EFI_ERROR (Status);
  313. }
  314. Size = sizeof (UINT32);
  315. Status = gRT->GetVariable (L"MmcForceDefaultSpeed",
  316. &gConfigDxeFormSetGuid,
  317. NULL, &Size, &Var32);
  318. if (EFI_ERROR (Status)) {
  319. Status = PcdSet32S (PcdMmcForceDefaultSpeed, PcdGet32 (PcdMmcForceDefaultSpeed));
  320. ASSERT_EFI_ERROR (Status);
  321. }
  322. Size = sizeof (UINT32);
  323. Status = gRT->GetVariable (L"MmcSdDefaultSpeedMHz",
  324. &gConfigDxeFormSetGuid,
  325. NULL, &Size, &Var32);
  326. if (EFI_ERROR (Status)) {
  327. Status = PcdSet32S (PcdMmcSdDefaultSpeedMHz, PcdGet32 (PcdMmcSdDefaultSpeedMHz));
  328. ASSERT_EFI_ERROR (Status);
  329. }
  330. Size = sizeof (UINT32);
  331. Status = gRT->GetVariable (L"MmcSdHighSpeedMHz",
  332. &gConfigDxeFormSetGuid,
  333. NULL, &Size, &Var32);
  334. if (EFI_ERROR (Status)) {
  335. Status = PcdSet32S (PcdMmcSdHighSpeedMHz, PcdGet32 (PcdMmcSdHighSpeedMHz));
  336. ASSERT_EFI_ERROR (Status);
  337. }
  338. Size = sizeof (UINT32);
  339. Status = gRT->GetVariable (L"MmcEnableDma",
  340. &gConfigDxeFormSetGuid,
  341. NULL, &Size, &Var32);
  342. if (EFI_ERROR (Status)) {
  343. Status = PcdSet32S (PcdMmcEnableDma, PcdGet32 (PcdMmcEnableDma));
  344. ASSERT_EFI_ERROR (Status);
  345. }
  346. Size = sizeof (UINT32);
  347. Status = gRT->GetVariable (L"DebugEnableJTAG",
  348. &gConfigDxeFormSetGuid,
  349. NULL, &Size, &Var32);
  350. if (EFI_ERROR (Status)) {
  351. Status = PcdSet32S (PcdDebugEnableJTAG, PcdGet32 (PcdDebugEnableJTAG));
  352. ASSERT_EFI_ERROR (Status);
  353. }
  354. Size = sizeof (UINT8);
  355. Status = gRT->GetVariable (L"DisplayEnableScaledVModes",
  356. &gConfigDxeFormSetGuid,
  357. NULL, &Size, &Var8);
  358. if (EFI_ERROR (Status)) {
  359. Status = PcdSet8S (PcdDisplayEnableScaledVModes, PcdGet8 (PcdDisplayEnableScaledVModes));
  360. ASSERT_EFI_ERROR (Status);
  361. }
  362. Size = sizeof (UINT32);
  363. Status = gRT->GetVariable (L"DisplayEnableSShot",
  364. &gConfigDxeFormSetGuid,
  365. NULL, &Size, &Var32);
  366. if (EFI_ERROR (Status)) {
  367. Status = PcdSet32S (PcdDisplayEnableSShot, PcdGet32 (PcdDisplayEnableSShot));
  368. ASSERT_EFI_ERROR (Status);
  369. }
  370. if (mModelFamily == 4) {
  371. //
  372. // Get the MAC address from the firmware.
  373. //
  374. Status = mFwProtocol->GetMacAddress (mMacAddress.Addr);
  375. if (EFI_ERROR (Status)) {
  376. DEBUG ((DEBUG_WARN, "%a: failed to retrieve MAC address\n", __FUNCTION__));
  377. }
  378. }
  379. return EFI_SUCCESS;
  380. }
  381. STATIC VOID
  382. ApplyVariables (
  383. VOID
  384. )
  385. {
  386. UINTN Gpio34Group;
  387. UINTN Gpio48Group;
  388. EFI_STATUS Status;
  389. UINT32 CpuClock = PcdGet32 (PcdCpuClock);
  390. UINT32 CustomCpuClock = PcdGet32 (PcdCustomCpuClock);
  391. UINT32 Rate = 0;
  392. UINT32 FanOnGpio = PcdGet32 (PcdFanOnGpio);
  393. switch (CpuClock) {
  394. case CHIPSET_CPU_CLOCK_LOW:
  395. Rate = FixedPcdGet32 (PcdCpuLowSpeedMHz) * FREQ_1_MHZ;
  396. break;
  397. case CHIPSET_CPU_CLOCK_DEFAULT:
  398. /*
  399. * What the Raspberry Pi Foundation calls "max clock rate" is really the default value
  400. * from: https://www.raspberrypi.org/documentation/configuration/config-txt/overclocking.md
  401. */
  402. Status = mFwProtocol->GetMaxClockRate (RPI_MBOX_CLOCK_RATE_ARM, &Rate);
  403. if (Status != EFI_SUCCESS) {
  404. DEBUG ((DEBUG_ERROR, "Couldn't read default CPU speed %r\n", Status));
  405. }
  406. break;
  407. case CHIPSET_CPU_CLOCK_MAX:
  408. Rate = FixedPcdGet32 (PcdCpuMaxSpeedMHz) * FREQ_1_MHZ;
  409. break;
  410. case CHIPSET_CPU_CLOCK_CUSTOM:
  411. Rate = CustomCpuClock * FREQ_1_MHZ;
  412. break;
  413. }
  414. if (Rate != 0) {
  415. DEBUG ((DEBUG_INFO, "Setting CPU speed to %u MHz\n", Rate / FREQ_1_MHZ));
  416. Status = mFwProtocol->SetClockRate (RPI_MBOX_CLOCK_RATE_ARM, Rate, 1);
  417. if (Status != EFI_SUCCESS) {
  418. DEBUG ((DEBUG_ERROR, "Couldn't set the CPU speed: %r\n", Status));
  419. } else {
  420. Status = PcdSet32S (PcdCustomCpuClock, Rate / FREQ_1_MHZ);
  421. ASSERT_EFI_ERROR (Status);
  422. }
  423. }
  424. Status = mFwProtocol->GetClockRate (RPI_MBOX_CLOCK_RATE_ARM, &Rate);
  425. if (Status != EFI_SUCCESS) {
  426. DEBUG ((DEBUG_ERROR, "Couldn't get the CPU speed: %r\n", Status));
  427. } else {
  428. DEBUG ((DEBUG_INFO, "Current CPU speed is %u MHz\n", Rate / FREQ_1_MHZ));
  429. }
  430. if (mModelFamily >= 4 && PcdGet32 (PcdRamMoreThan3GB) != 0 &&
  431. PcdGet32 (PcdRamLimitTo3GB) == 0) {
  432. UINT64 SystemMemorySize;
  433. UINT64 SystemMemorySizeBelow4GB;
  434. ASSERT (BCM2711_SOC_REGISTERS != 0);
  435. SystemMemorySize = (UINT64)mModelInstalledMB * SIZE_1MB;
  436. /*
  437. * Similar to how we compute the > 3 GB RAM segment's size in PlatformLib/
  438. * RaspberryPiMem.c, with some overlap protection for the Bcm2xxx register
  439. * spaces. SystemMemorySizeBelow4GB tracks the maximum memory below 4GB
  440. * line, factoring in the limit imposed by the SoC register range.
  441. */
  442. SystemMemorySizeBelow4GB = MIN (SystemMemorySize, 4UL * SIZE_1GB);
  443. SystemMemorySizeBelow4GB = MIN (SystemMemorySizeBelow4GB, BCM2836_SOC_REGISTERS);
  444. SystemMemorySizeBelow4GB = MIN (SystemMemorySizeBelow4GB, BCM2711_SOC_REGISTERS);
  445. ASSERT (SystemMemorySizeBelow4GB > 3UL * SIZE_1GB);
  446. Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, 3UL * BASE_1GB,
  447. SystemMemorySizeBelow4GB - (3UL * SIZE_1GB),
  448. EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB);
  449. ASSERT_EFI_ERROR (Status);
  450. Status = gDS->SetMemorySpaceAttributes (3UL * BASE_1GB,
  451. SystemMemorySizeBelow4GB - (3UL * SIZE_1GB), EFI_MEMORY_WB);
  452. ASSERT_EFI_ERROR (Status);
  453. if (SystemMemorySize > 4UL * SIZE_1GB) {
  454. //
  455. // Register any memory above 4GB.
  456. //
  457. Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, 4UL * BASE_1GB,
  458. SystemMemorySize - (4UL * SIZE_1GB),
  459. EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB);
  460. ASSERT_EFI_ERROR (Status);
  461. Status = gDS->SetMemorySpaceAttributes (4UL * BASE_1GB,
  462. SystemMemorySize - (4UL * SIZE_1GB), EFI_MEMORY_WB);
  463. ASSERT_EFI_ERROR (Status);
  464. }
  465. }
  466. if (mModelFamily == 3 || mModelFamily == 2) {
  467. /*
  468. * Pi 2B v1.2 / Pi 3: either Arasan or SdHost goes to SD card.
  469. *
  470. * Switching two groups around, so disable both first.
  471. *
  472. * No, I've not seen a problem, but having a group be
  473. * routed to two sets of pins seems like asking for trouble.
  474. */
  475. GpioPinFuncSet (34, GPIO_FSEL_INPUT);
  476. GpioPinFuncSet (35, GPIO_FSEL_INPUT);
  477. GpioPinFuncSet (36, GPIO_FSEL_INPUT);
  478. GpioPinFuncSet (37, GPIO_FSEL_INPUT);
  479. GpioPinFuncSet (38, GPIO_FSEL_INPUT);
  480. GpioPinFuncSet (39, GPIO_FSEL_INPUT);
  481. GpioPinFuncSet (48, GPIO_FSEL_INPUT);
  482. GpioPinFuncSet (49, GPIO_FSEL_INPUT);
  483. GpioPinFuncSet (50, GPIO_FSEL_INPUT);
  484. GpioPinFuncSet (51, GPIO_FSEL_INPUT);
  485. GpioPinFuncSet (52, GPIO_FSEL_INPUT);
  486. GpioPinFuncSet (53, GPIO_FSEL_INPUT);
  487. if (PcdGet32 (PcdSdIsArasan)) {
  488. DEBUG ((DEBUG_INFO, "Routing SD to Arasan\n"));
  489. Gpio48Group = GPIO_FSEL_ALT3;
  490. /*
  491. * Route SDIO to SdHost.
  492. */
  493. Gpio34Group = GPIO_FSEL_ALT0;
  494. } else {
  495. DEBUG ((DEBUG_INFO, "Routing SD to SdHost\n"));
  496. Gpio48Group = GPIO_FSEL_ALT0;
  497. /*
  498. * Route SDIO to Arasan.
  499. */
  500. Gpio34Group = GPIO_FSEL_ALT3;
  501. }
  502. GpioPinFuncSet (34, Gpio34Group);
  503. GpioPinFuncSet (35, Gpio34Group);
  504. GpioPinFuncSet (36, Gpio34Group);
  505. GpioPinFuncSet (37, Gpio34Group);
  506. GpioPinFuncSet (38, Gpio34Group);
  507. GpioPinFuncSet (39, Gpio34Group);
  508. GpioPinFuncSet (48, Gpio48Group);
  509. GpioPinFuncSet (49, Gpio48Group);
  510. GpioPinFuncSet (50, Gpio48Group);
  511. GpioPinFuncSet (51, Gpio48Group);
  512. GpioPinFuncSet (52, Gpio48Group);
  513. GpioPinFuncSet (53, Gpio48Group);
  514. } else if (mModelFamily == 4) {
  515. /*
  516. * Pi 4: either Arasan or eMMC2 goes to SD card.
  517. */
  518. if (PcdGet32 (PcdSdIsArasan)) {
  519. /*
  520. * WiFi disabled.
  521. */
  522. GpioPinFuncSet (34, GPIO_FSEL_INPUT);
  523. GpioPinFuncSet (35, GPIO_FSEL_INPUT);
  524. GpioPinFuncSet (36, GPIO_FSEL_INPUT);
  525. GpioPinFuncSet (37, GPIO_FSEL_INPUT);
  526. GpioPinFuncSet (38, GPIO_FSEL_INPUT);
  527. GpioPinFuncSet (39, GPIO_FSEL_INPUT);
  528. /*
  529. * SD card pins go to Arasan.
  530. */
  531. MmioOr32 (GPIO_BASE_ADDRESS + 0xD0, BIT1);
  532. } else {
  533. /*
  534. * SD card pins back to eMMC2.
  535. */
  536. MmioAnd32 (GPIO_BASE_ADDRESS + 0xD0, ~BIT1);
  537. /*
  538. * WiFi back to Arasan.
  539. */
  540. GpioPinFuncSet (34, GPIO_FSEL_ALT3);
  541. GpioPinFuncSet (35, GPIO_FSEL_ALT3);
  542. GpioPinFuncSet (36, GPIO_FSEL_ALT3);
  543. GpioPinFuncSet (37, GPIO_FSEL_ALT3);
  544. GpioPinFuncSet (38, GPIO_FSEL_ALT3);
  545. GpioPinFuncSet (39, GPIO_FSEL_ALT3);
  546. Status = mFwProtocol->SetPowerState (RPI_MBOX_POWER_STATE_SDHCI,
  547. TRUE, TRUE); //SD on with wait
  548. Status = mFwProtocol->SetGpioConfig (RPI_EXP_GPIO_SD_VOLT,
  549. RPI_EXP_GPIO_DIR_OUT, TRUE); //3.3v
  550. Status = mFwProtocol->SetClockState (RPI_MBOX_CLOCK_RATE_EMMC2, TRUE);
  551. Status = mFwProtocol->SetClockState (RPI_MBOX_CLOCK_RATE_EMMC, TRUE);
  552. }
  553. } else {
  554. DEBUG ((DEBUG_ERROR, "Model Family %d not supported...\n", mModelFamily));
  555. }
  556. /*
  557. * JTAG pin JTAG sig GPIO Mode Header pin
  558. * 1 VREF N/A 1
  559. * 3 nTRST GPIO22 ALT4 15
  560. * 4 GND N/A 9
  561. * 5 TDI GPIO26 ALT4 37
  562. * 7 TMS GPIO27 ALT4 13
  563. * 9 TCK GPIO25 ALT4 22
  564. * 11 RTCK GPIO23 ALT4 16
  565. * 13 TDO GPIO24 ALT4 18
  566. */
  567. if (PcdGet32 (PcdDebugEnableJTAG)) {
  568. GpioPinFuncSet (22, GPIO_FSEL_ALT4);
  569. GpioPinFuncSet (26, GPIO_FSEL_ALT4);
  570. GpioPinFuncSet (27, GPIO_FSEL_ALT4);
  571. GpioPinFuncSet (25, GPIO_FSEL_ALT4);
  572. GpioPinFuncSet (23, GPIO_FSEL_ALT4);
  573. GpioPinFuncSet (24, GPIO_FSEL_ALT4);
  574. } else {
  575. GpioPinFuncSet (22, GPIO_FSEL_INPUT);
  576. GpioPinFuncSet (26, GPIO_FSEL_INPUT);
  577. GpioPinFuncSet (27, GPIO_FSEL_INPUT);
  578. GpioPinFuncSet (25, GPIO_FSEL_INPUT);
  579. GpioPinFuncSet (23, GPIO_FSEL_INPUT);
  580. GpioPinFuncSet (24, GPIO_FSEL_INPUT);
  581. }
  582. if (FanOnGpio) {
  583. DEBUG ((DEBUG_INFO, "Fan enabled on GPIO %d\n", FanOnGpio));
  584. GpioPinFuncSet (FanOnGpio, GPIO_FSEL_OUTPUT);
  585. }
  586. //
  587. // Fake the CTS signal as we don't support HW flow control yet.
  588. // Pin 31 must be held LOW so that we can talk to the BT chip
  589. // without flow control
  590. //
  591. GpioPinFuncSet (31, GPIO_FSEL_OUTPUT);
  592. GpioPinConfigure (31, CLEAR_GPIO);
  593. //
  594. // Bluetooth pin muxing
  595. //
  596. if ((PcdGet32 (PcdUartInUse) == PL011_UART_IN_USE)) {
  597. DEBUG ((DEBUG_INFO, "Enable Bluetooth over MiniUART\n"));
  598. GpioPinFuncSet (32, GPIO_FSEL_ALT5);
  599. GpioPinFuncSet (33, GPIO_FSEL_ALT5);
  600. } else {
  601. DEBUG ((DEBUG_INFO, "Enable Bluetooth over PL011 UART\n"));
  602. GpioPinFuncSet (32, GPIO_FSEL_ALT3);
  603. GpioPinFuncSet (33, GPIO_FSEL_ALT3);
  604. }
  605. }
  606. typedef struct {
  607. CHAR8 Name[4];
  608. UINTN PcdToken;
  609. } AML_NAME_OP_REPLACE;
  610. typedef struct {
  611. UINT64 OemTableId;
  612. UINTN PcdToken;
  613. UINTN PcdTokenNot;
  614. CONST AML_NAME_OP_REPLACE *SdtNameOpReplace;
  615. } NAMESPACE_TABLES;
  616. #define SSDT_PATTERN_LEN 5
  617. #define AML_NAMEOP_8 0x0A
  618. #define AML_NAMEOP_16 0x0B
  619. #define AML_NAMEOP_32 0x0C
  620. #define AML_NAMEOP_STR 0x0D
  621. //
  622. // Scan the given namespace table (DSDT/SSDT) for AML NameOps
  623. // listed in the NameOpReplace structure. If one is found then
  624. // update the value in the table from the specified Pcd
  625. //
  626. // This allows us to have conditionals in AML controlled
  627. // by options in the BDS or detected during firmware bootstrap.
  628. // We could extend this concept for strings/etc but due to len
  629. // variations its probably easier to encode the strings
  630. // in the ASL and pick the correct one based off a variable.
  631. //
  632. STATIC
  633. VOID
  634. UpdateSdtNameOps (
  635. EFI_ACPI_DESCRIPTION_HEADER *AcpiTable,
  636. CONST AML_NAME_OP_REPLACE *NameOpReplace
  637. )
  638. {
  639. UINTN Idx;
  640. UINTN Index;
  641. CHAR8 Pattern[SSDT_PATTERN_LEN];
  642. UINTN PcdVal;
  643. UINT8 *SdtPtr;
  644. UINT32 SdtSize;
  645. SdtSize = AcpiTable->Length;
  646. if (SdtSize > 0) {
  647. SdtPtr = (UINT8 *)AcpiTable;
  648. for (Idx = 0; NameOpReplace && NameOpReplace[Idx].PcdToken; Idx++) {
  649. //
  650. // Do a single NameOp variable replacement these are of the
  651. // form 08 XXXX SIZE VAL, where SIZE is 0A=byte, 0B=word, 0C=dword
  652. // and XXXX is the name and VAL is the value
  653. //
  654. Pattern[0] = 0x08;
  655. Pattern[1] = NameOpReplace[Idx].Name[0];
  656. Pattern[2] = NameOpReplace[Idx].Name[1];
  657. Pattern[3] = NameOpReplace[Idx].Name[2];
  658. Pattern[4] = NameOpReplace[Idx].Name[3];
  659. for (Index = 0; Index < (SdtSize - SSDT_PATTERN_LEN); Index++) {
  660. if (CompareMem (SdtPtr + Index, Pattern, SSDT_PATTERN_LEN) == 0) {
  661. PcdVal = LibPcdGet32 (NameOpReplace[Idx].PcdToken);
  662. switch (SdtPtr[Index + SSDT_PATTERN_LEN]) {
  663. case AML_NAMEOP_32:
  664. SdtPtr[Index + SSDT_PATTERN_LEN + 4] = (PcdVal >> 24) & 0xFF;
  665. SdtPtr[Index + SSDT_PATTERN_LEN + 3] = (PcdVal >> 16) & 0xFF;
  666. // Fallthrough
  667. case AML_NAMEOP_16:
  668. SdtPtr[Index + SSDT_PATTERN_LEN + 2] = (PcdVal >> 8) & 0xFF;
  669. // Fallthrough
  670. case AML_NAMEOP_8:
  671. SdtPtr[Index + SSDT_PATTERN_LEN + 1] = PcdVal & 0xFF;
  672. break;
  673. case 0:
  674. case 1:
  675. SdtPtr[Index + SSDT_PATTERN_LEN + 1] = !!PcdVal;
  676. break;
  677. case AML_NAMEOP_STR:
  678. //
  679. // If the string val is added to the NameOpReplace, we can
  680. // dynamically update things like _HID too as long as the
  681. // string length matches.
  682. //
  683. break;
  684. }
  685. break;
  686. }
  687. }
  688. }
  689. }
  690. }
  691. STATIC
  692. BOOLEAN
  693. VerifyUpdateTable (
  694. IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader,
  695. IN CONST NAMESPACE_TABLES *SdtTable
  696. )
  697. {
  698. BOOLEAN Result;
  699. Result = TRUE;
  700. if (SdtTable->PcdToken && !LibPcdGet32 (SdtTable->PcdToken)) {
  701. Result = FALSE;
  702. }
  703. if (SdtTable->PcdTokenNot && LibPcdGet32 (SdtTable->PcdTokenNot)) {
  704. Result = FALSE;
  705. }
  706. if (Result && SdtTable->SdtNameOpReplace) {
  707. UpdateSdtNameOps (AcpiHeader, SdtTable->SdtNameOpReplace);
  708. }
  709. return Result;
  710. }
  711. STATIC CONST AML_NAME_OP_REPLACE SsdtNameOpReplace[] = {
  712. { "GIOP", PcdToken (PcdFanOnGpio) },
  713. { "FTMP", PcdToken (PcdFanTemp) },
  714. { }
  715. };
  716. STATIC CONST AML_NAME_OP_REPLACE SsdtEmmcNameOpReplace[] = {
  717. { "SDMA", PcdToken (PcdMmcEnableDma) },
  718. { }
  719. };
  720. STATIC CONST AML_NAME_OP_REPLACE DsdtNameOpReplace[] = {
  721. { "URIU", PcdToken (PcdUartInUse) },
  722. { "MUCR", PcdToken (PcdMiniUartClockRate) },
  723. { }
  724. };
  725. STATIC CONST NAMESPACE_TABLES SdtTables[] = {
  726. {
  727. SIGNATURE_64 ('R', 'P', 'I', 'T', 'H', 'F', 'A', 'N'),
  728. PcdToken(PcdFanOnGpio),
  729. 0,
  730. SsdtNameOpReplace
  731. },
  732. {
  733. SIGNATURE_64 ('R', 'P', 'I', '4', 'E', 'M', 'M', 'C'),
  734. 0,
  735. PcdToken(PcdSdIsArasan),
  736. SsdtEmmcNameOpReplace
  737. },
  738. #if (RPI_MODEL == 4)
  739. {
  740. SIGNATURE_64 ('R', 'P', 'I', '4', 'X', 'H', 'C', 'I'),
  741. 0,
  742. PcdToken(PcdXhciPci),
  743. NULL
  744. },
  745. {
  746. SIGNATURE_64 ('R', 'P', 'I', '4', 'P', 'C', 'I', 'E'),
  747. PcdToken(PcdXhciPci),
  748. 0,
  749. NULL
  750. },
  751. #endif
  752. { // DSDT
  753. SIGNATURE_64 ('R', 'P', 'I', 0, 0, 0, 0, 0),
  754. 0,
  755. 0,
  756. DsdtNameOpReplace
  757. },
  758. { }
  759. };
  760. //
  761. // Monitor the ACPI tables being installed and when
  762. // a DSDT/SSDT is detected validate that we want to
  763. // install it, and if so update any "NameOp" defined
  764. // variables contained in the table from PCD values
  765. //
  766. STATIC
  767. BOOLEAN
  768. HandleDynamicNamespace (
  769. IN EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader
  770. )
  771. {
  772. UINTN Tables;
  773. EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *SpcrTable;
  774. DBG2_TABLE *Dbg2Table;
  775. switch (AcpiHeader->Signature) {
  776. case SIGNATURE_32 ('D', 'S', 'D', 'T'):
  777. case SIGNATURE_32 ('S', 'S', 'D', 'T'):
  778. for (Tables = 0; SdtTables[Tables].OemTableId; Tables++) {
  779. if (AcpiHeader->OemTableId == SdtTables[Tables].OemTableId) {
  780. return VerifyUpdateTable (AcpiHeader, &SdtTables[Tables]);
  781. }
  782. }
  783. DEBUG ((DEBUG_ERROR, "Found namespace table not in table list.\n"));
  784. return FALSE;
  785. case SIGNATURE_32 ('I', 'O', 'R', 'T'):
  786. // only enable the IORT on machines with >3G and no limit
  787. // to avoid problems with rhel/centos and other older OSs
  788. if (PcdGet32 (PcdRamLimitTo3GB) || !PcdGet32 (PcdRamMoreThan3GB)) {
  789. return FALSE;
  790. }
  791. return TRUE;
  792. case SIGNATURE_32 ('S', 'P', 'C', 'R'):
  793. SpcrTable = (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE *)AcpiHeader;
  794. if ((PcdGet32 (PcdUartInUse) == PL011_UART_IN_USE) &&
  795. (SpcrTable->InterfaceType == EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_ARM_PL011_UART)) {
  796. return TRUE;
  797. } else if ((PcdGet32 (PcdUartInUse) == MINI_UART_IN_USE) &&
  798. (SpcrTable->InterfaceType == EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_BCM2835_UART)) {
  799. return TRUE;
  800. }
  801. return FALSE;
  802. case SIGNATURE_32 ('D', 'B', 'G', '2'):
  803. Dbg2Table = (DBG2_TABLE *)AcpiHeader;
  804. if ((PcdGet32 (PcdUartInUse) == PL011_UART_IN_USE) &&
  805. (Dbg2Table->Dbg2DeviceInfo[0].Dbg2Device.PortSubtype == EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART)) {
  806. return TRUE;
  807. } else if ((PcdGet32 (PcdUartInUse) == MINI_UART_IN_USE) &&
  808. (Dbg2Table->Dbg2DeviceInfo[0].Dbg2Device.PortSubtype == EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_BCM2835_UART)) {
  809. return TRUE;
  810. }
  811. return FALSE;
  812. }
  813. return TRUE;
  814. }
  815. EFI_STATUS
  816. EFIAPI
  817. ConfigInitialize (
  818. IN EFI_HANDLE ImageHandle,
  819. IN EFI_SYSTEM_TABLE *SystemTable
  820. )
  821. {
  822. EFI_STATUS Status;
  823. EFI_EVENT EndOfDxeEvent;
  824. if ((MmioRead32(GPIO_GPFSEL1) & GPFSEL1_UART_MASK) == PL011_UART_IN_USE_REG_VALUE) {
  825. PcdSet32S (PcdUartInUse, PL011_UART_IN_USE);
  826. } else if ((MmioRead32(GPIO_GPFSEL1) & GPFSEL1_UART_MASK) == MINI_UART_IN_USE_REG_VALUE) {
  827. PcdSet32S (PcdUartInUse, MINI_UART_IN_USE);
  828. }
  829. Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid,
  830. NULL, (VOID**)&mFwProtocol);
  831. ASSERT_EFI_ERROR (Status);
  832. if (EFI_ERROR (Status)) {
  833. return Status;
  834. }
  835. Status = mFwProtocol->GetModelFamily (&mModelFamily);
  836. if (Status != EFI_SUCCESS) {
  837. DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi model family: %r\n", Status));
  838. } else {
  839. DEBUG ((DEBUG_INFO, "Current Raspberry Pi model family is %d\n", mModelFamily));
  840. }
  841. Status = mFwProtocol->GetModelInstalledMB (&mModelInstalledMB);
  842. if (Status != EFI_SUCCESS) {
  843. DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi installed RAM size: %r\n", Status));
  844. } else {
  845. DEBUG ((DEBUG_INFO, "Current Raspberry Pi installed RAM size is %d MB\n", mModelInstalledMB));
  846. }
  847. Status = mFwProtocol->GetModelRevision (&mModelRevision);
  848. if (Status != EFI_SUCCESS) {
  849. DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi revision: %r\n", Status));
  850. } else {
  851. DEBUG ((DEBUG_INFO, "Current Raspberry Pi revision %x\n", mModelRevision));
  852. }
  853. Status = mFwProtocol->GetClockRate (RPI_MBOX_CLOCK_RATE_CORE, &mCoreClockRate);
  854. if (Status != EFI_SUCCESS) {
  855. DEBUG ((DEBUG_ERROR, "Couldn't get the Raspberry Pi core clock rate: %r\n", Status));
  856. } else {
  857. PcdSet32S (PcdMiniUartClockRate, mCoreClockRate);
  858. }
  859. Status = SetupVariables ();
  860. if (Status != EFI_SUCCESS) {
  861. DEBUG ((DEBUG_ERROR, "Couldn't not setup NV vars: %r\n", Status));
  862. }
  863. ApplyVariables ();
  864. Status = gBS->InstallProtocolInterface (&ImageHandle,
  865. &gRaspberryPiConfigAppliedProtocolGuid,
  866. EFI_NATIVE_INTERFACE,
  867. NULL);
  868. ASSERT_EFI_ERROR (Status);
  869. Status = InstallHiiPages ();
  870. if (Status != EFI_SUCCESS) {
  871. DEBUG ((DEBUG_ERROR, "Couldn't install ConfigDxe configuration pages: %r\n", Status));
  872. }
  873. if (PcdGet32 (PcdSystemTableMode) == SYSTEM_TABLE_MODE_ACPI ||
  874. PcdGet32 (PcdSystemTableMode) == SYSTEM_TABLE_MODE_BOTH) {
  875. Status = LocateAndInstallAcpiFromFvConditional (&mAcpiTableFile,
  876. &HandleDynamicNamespace);
  877. ASSERT_EFI_ERROR (Status);
  878. }
  879. Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RegisterDevices,
  880. NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent);
  881. ASSERT_EFI_ERROR (Status);
  882. if (mModelFamily == 4) {
  883. RegisterXhciQuirkHandler (mFwProtocol);
  884. }
  885. return EFI_SUCCESS;
  886. }