smbios.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. smbios.c
  5. Abstract:
  6. This module implements SMBIOS tables for the Raspberry Pi 2.
  7. Author:
  8. Chris Stevens 19-Mar-2015
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/lib/types.h>
  16. #include <minoca/lib/status.h>
  17. #include <minoca/lib/rtl.h>
  18. #include <minoca/fw/smbios.h>
  19. #include "uefifw.h"
  20. #include "rpi2fw.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // Set the build date and version to a hardcoded value to avoid the SMBIOS
  26. // table changing from build to build. The automated tests checksum the whole
  27. // table to get a machine ID, so if the dates or versions change then each
  28. // new firmware iteration looks like an entirely new machine.
  29. //
  30. #define RPI2_FIRMWARE_VERSION_MAJOR 1
  31. #define RPI2_FIRMWARE_VERSION_MINOR 1
  32. #define RPI2_FIRMWARE_VERSION_STRING "1.1"
  33. #define RPI2_FIRMWARE_VERSION_DATE "05/06/2016"
  34. //
  35. // Define the SMBIOS values common between the RPI 2 and RPI 3.
  36. //
  37. #define RPI2_SMBIOS_BIOS_VENDOR "Minoca Corp"
  38. #define RPI2_SMBIOS_SYSTEM_MANUFACTURER "Raspberry Pi Foundation"
  39. #define RPI2_SMBIOS_SYSTEM_PRODUCT_NAME "Raspberry Pi"
  40. #define RPI2_SMBIOS_MODULE_MANUFACTURER "Raspberry Pi Foundation"
  41. #define RPI2_SMBIOS_MODULE_PRODUCT "Raspberry Pi"
  42. #define RPI2_SMBIOS_PROCESSOR_MANUFACTURER "Broadcom"
  43. #define RPI2_SMBIOS_PROCESSOR_CORE_COUNT 4
  44. #define RPI2_SMBIOS_CACHE_L1_SIZE 32
  45. //
  46. // Define the SMBIOS values that differ betweent the RPI 2 and RPI3.
  47. //
  48. #define RPI2_SMBIOS_PROCESSOR_PART "BCM2836"
  49. #define RPI3_SMBIOS_PROCESSOR_PART "BCM2837"
  50. #define HERTZ_PER_MEGAHERTZ 1000000ULL
  51. //
  52. // ------------------------------------------------------ Data Type Definitions
  53. //
  54. /*++
  55. Structure Description:
  56. This structure defines the data necessary to query the BCM2709 video core
  57. for SMBIOS related information.
  58. Members:
  59. Header - Stores a header that defines the total size of the messages being
  60. sent to and received from the mailbox.
  61. RevisionMessage - Stores a message indicating that the board's revision is
  62. being queried. Contains the revision on return.
  63. SerialMessage - Stores a messagin indicating that the board's serial number
  64. is being queried. Contains the serial number on return.
  65. ArmClockRate - Stores a message requesting the ARM core's clock rate.
  66. ArmMaxClockRate - Stores a message requesting the ARM core's maximum clock
  67. rate.
  68. EndTag - Stores the tag to denote the end of the mailbox message.
  69. --*/
  70. typedef struct _EFI_BCM2709_GET_SMBIOS_INFORMATION {
  71. BCM2709_MAILBOX_HEADER Header;
  72. BCM2709_MAILBOX_BOARD_REVISION RevisionMessage;
  73. BCM2709_MAILBOX_BOARD_SERIAL_NUMBER SerialMessage;
  74. BCM2709_MAILBOX_GET_CLOCK_RATE ArmClockRate;
  75. BCM2709_MAILBOX_GET_CLOCK_RATE ArmMaxClockRate;
  76. BCM2709_MAILBOX_GET_CLOCK_RATE ApbClockRate;
  77. UINT32 EndTag;
  78. } EFI_BCM2709_GET_SMBIOS_INFORMATION, *PEFI_BCM2709_GET_SMBIOS_INFORMATION;
  79. /*++
  80. Structure Description:
  81. This structure defines a Raspberry Pi revision.
  82. Members:
  83. Revision - Stores the Raspberry Pi revision number.
  84. Name - Stores the friendly name of the revision.
  85. ProcessorPart - Stores the processor part used by the revision.
  86. --*/
  87. typedef struct _RPI2_REVISION {
  88. UINT32 Revision;
  89. CHAR8 *Name;
  90. CHAR8 *ProcessorPart;
  91. } RPI2_REVISION, *PRPI2_REVISION;
  92. //
  93. // ----------------------------------------------- Internal Function Prototypes
  94. //
  95. //
  96. // -------------------------------------------------------------------- Globals
  97. //
  98. SMBIOS_BIOS_INFORMATION EfiRpi2SmbiosBiosInformation = {
  99. {
  100. SmbiosBiosInformation,
  101. sizeof(SMBIOS_BIOS_INFORMATION),
  102. 0x0100
  103. },
  104. 1,
  105. 2,
  106. 0,
  107. 3,
  108. 0,
  109. SMBIOS_BIOS_CHARACTERISTIC_UNSUPPORTED,
  110. 0,
  111. RPI2_FIRMWARE_VERSION_MAJOR,
  112. RPI2_FIRMWARE_VERSION_MINOR,
  113. 0,
  114. 0
  115. };
  116. SMBIOS_SYSTEM_INFORMATION EfiRpi2SmbiosSystemInformation = {
  117. {
  118. SmbiosSystemInformation,
  119. sizeof(SMBIOS_SYSTEM_INFORMATION),
  120. 0x0101
  121. },
  122. 1,
  123. 2,
  124. 3,
  125. 4,
  126. {0},
  127. SMBIOS_SYSTEM_WAKEUP_UNKNOWN,
  128. 3,
  129. 2
  130. };
  131. SMBIOS_MODULE_INFORMATION EfiRpi2SmbiosModuleInformation = {
  132. {
  133. SmbiosModuleInformation,
  134. sizeof(SMBIOS_MODULE_INFORMATION),
  135. 0x0102
  136. },
  137. 1,
  138. 2,
  139. 0,
  140. 0,
  141. 0,
  142. SMBIOS_MODULE_MOTHERBOARD,
  143. 0,
  144. 0x0104,
  145. SMBIOS_MODULE_TYPE_MOTHERBOARD,
  146. 0
  147. };
  148. SMBIOS_ENCLOSURE EfiRpi2SmbiosEnclosure = {
  149. {
  150. SmbiosSystemEnclosure,
  151. sizeof(SMBIOS_ENCLOSURE),
  152. 0x0104
  153. },
  154. 0,
  155. SMBIOS_ENCLOSURE_TYPE_UNKNOWN,
  156. 0,
  157. 0,
  158. 0,
  159. SMBIOS_ENCLOSURE_STATE_UNKNOWN,
  160. SMBIOS_ENCLOSURE_STATE_UNKNOWN,
  161. SMBIOS_ENCLOSURE_SECURITY_STATE_UNKNOWN,
  162. 0,
  163. 0,
  164. 0,
  165. 0,
  166. 0,
  167. 0
  168. };
  169. SMBIOS_PROCESSOR_INFORMATION EfiRpi2SmbiosProcessorInformation = {
  170. {
  171. SmbiosProcessorInformation,
  172. sizeof(SMBIOS_PROCESSOR_INFORMATION),
  173. 0x0105
  174. },
  175. 0,
  176. SMBIOS_PROCESSOR_TYPE_CENTRAL_PROCESSOR,
  177. 0x2,
  178. 1,
  179. 0,
  180. 0,
  181. 0,
  182. 0,
  183. 0,
  184. 0,
  185. SMBIOS_PROCESSOR_STATUS_ENABLED,
  186. 0,
  187. 0x0106,
  188. 0xFFFF,
  189. 0xFFFF,
  190. 2,
  191. 0,
  192. 3,
  193. RPI2_SMBIOS_PROCESSOR_CORE_COUNT,
  194. 0,
  195. SMBIOS_PROCESSOR_CHARACTERISTIC_UNKNOWN,
  196. 0
  197. };
  198. SMBIOS_CACHE_INFORMATION EfiRpi2SmbiosL1Cache = {
  199. {
  200. SmbiosCacheInformation,
  201. sizeof(SMBIOS_CACHE_INFORMATION),
  202. 0x0106
  203. },
  204. 0,
  205. SMBIOS_CACHE_ENABLED | SMBIOS_CACHE_WRITE_BACK,
  206. RPI2_SMBIOS_CACHE_L1_SIZE,
  207. RPI2_SMBIOS_CACHE_L1_SIZE,
  208. SMBIOS_CACHE_SRAM_UNKNOWN,
  209. SMBIOS_CACHE_SRAM_UNKNOWN,
  210. 0,
  211. SMBIOS_CACHE_ERROR_CORRECTION_NONE,
  212. SMBIOS_CACHE_TYPE_DATA,
  213. SMBIOS_CACHE_ASSOCIATIVITY_4_WAY_SET
  214. };
  215. EFI_BCM2709_GET_SMBIOS_INFORMATION EfiRpi2BoardInformationTemplate = {
  216. {
  217. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION),
  218. 0
  219. },
  220. {
  221. {
  222. BCM2709_MAILBOX_TAG_GET_BOARD_REVISION,
  223. sizeof(UINT32),
  224. 0
  225. },
  226. 0
  227. },
  228. {
  229. {
  230. BCM2709_MAILBOX_TAG_GET_BOARD_SERIAL,
  231. sizeof(UINT32) * 2,
  232. 0
  233. },
  234. {0, 0}
  235. },
  236. {
  237. {
  238. BCM2709_MAILBOX_TAG_GET_CLOCK_RATE,
  239. sizeof(UINT32) + sizeof(UINT32),
  240. sizeof(UINT32)
  241. },
  242. BCM2709_MAILBOX_CLOCK_ID_ARM,
  243. 0
  244. },
  245. {
  246. {
  247. BCM2709_MAILBOX_TAG_GET_CLOCK_MAX_RATE,
  248. sizeof(UINT32) + sizeof(UINT32),
  249. sizeof(UINT32)
  250. },
  251. BCM2709_MAILBOX_CLOCK_ID_ARM,
  252. 0
  253. },
  254. {
  255. {
  256. BCM2709_MAILBOX_TAG_GET_CLOCK_RATE,
  257. sizeof(UINT32) + sizeof(UINT32),
  258. sizeof(UINT32)
  259. },
  260. BCM2709_MAILBOX_CLOCK_ID_VIDEO,
  261. 0
  262. },
  263. 0
  264. };
  265. RPI2_REVISION EfiRpi2Revisions[] = {
  266. {0x00a01041, "2 Model B Rev 1.1", RPI2_SMBIOS_PROCESSOR_PART},
  267. {0x00a21041, "2 Model B Rev 1.1", RPI2_SMBIOS_PROCESSOR_PART},
  268. {0x00a02082, "3 Model B Rev 1.2", RPI3_SMBIOS_PROCESSOR_PART},
  269. {0x00a22082, "3 Model B Rev 1.2", RPI3_SMBIOS_PROCESSOR_PART},
  270. };
  271. //
  272. // ------------------------------------------------------------------ Functions
  273. //
  274. EFI_STATUS
  275. EfipRpi2CreateSmbiosTables (
  276. VOID
  277. )
  278. /*++
  279. Routine Description:
  280. This routine creates the SMBIOS tables.
  281. Arguments:
  282. None.
  283. Return Value:
  284. EFI Status code.
  285. --*/
  286. {
  287. EFI_BCM2709_GET_SMBIOS_INFORMATION BoardInformation;
  288. UINT32 ExpectedLength;
  289. UINT32 Index;
  290. UINT32 Length;
  291. CHAR8 *ProcessorPart;
  292. CHAR8 ProductBuffer[32];
  293. CHAR8 *ProductName;
  294. PRPI2_REVISION Revision;
  295. UINT32 RevisionCount;
  296. CHAR8 SerialNumber[17];
  297. EFI_STATUS Status;
  298. CHAR8 Version[13];
  299. //
  300. // Query the BMC2836 mailbox to get version information and a serial number.
  301. //
  302. EfiCopyMem(&BoardInformation,
  303. &EfiRpi2BoardInformationTemplate,
  304. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION));
  305. Status = EfipBcm2709MailboxSendCommand(
  306. BCM2709_MAILBOX_PROPERTIES_CHANNEL,
  307. &BoardInformation,
  308. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION),
  309. FALSE);
  310. if (EFI_ERROR(Status)) {
  311. return Status;
  312. }
  313. Length = BoardInformation.RevisionMessage.TagHeader.Length;
  314. ExpectedLength = sizeof(BCM2709_MAILBOX_BOARD_REVISION) -
  315. sizeof(BCM2709_MAILBOX_TAG);
  316. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  317. return EFI_DEVICE_ERROR;
  318. }
  319. Length = BoardInformation.SerialMessage.TagHeader.Length;
  320. ExpectedLength = sizeof(BCM2709_MAILBOX_BOARD_SERIAL_NUMBER) -
  321. sizeof(BCM2709_MAILBOX_TAG);
  322. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  323. return EFI_DEVICE_ERROR;
  324. }
  325. Length = BoardInformation.ArmClockRate.TagHeader.Length;
  326. ExpectedLength = sizeof(BCM2709_MAILBOX_GET_CLOCK_RATE) -
  327. sizeof(BCM2709_MAILBOX_TAG);
  328. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  329. return EFI_DEVICE_ERROR;
  330. }
  331. Length = BoardInformation.ArmMaxClockRate.TagHeader.Length;
  332. ExpectedLength = sizeof(BCM2709_MAILBOX_GET_CLOCK_RATE) -
  333. sizeof(BCM2709_MAILBOX_TAG);
  334. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  335. return EFI_DEVICE_ERROR;
  336. }
  337. Length = BoardInformation.ApbClockRate.TagHeader.Length;
  338. ExpectedLength = sizeof(BCM2709_MAILBOX_GET_CLOCK_RATE) -
  339. sizeof(BCM2709_MAILBOX_TAG);
  340. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  341. return EFI_DEVICE_ERROR;
  342. }
  343. //
  344. // Update the clock information.
  345. //
  346. EfiRpi2SmbiosProcessorInformation.MaxSpeed =
  347. BoardInformation.ArmMaxClockRate.Rate / HERTZ_PER_MEGAHERTZ;
  348. EfiRpi2SmbiosProcessorInformation.CurrentSpeed =
  349. BoardInformation.ArmClockRate.Rate / HERTZ_PER_MEGAHERTZ;
  350. EfiRpi2SmbiosProcessorInformation.ExternalClock =
  351. BoardInformation.ApbClockRate.Rate / HERTZ_PER_MEGAHERTZ;
  352. //
  353. // Convert the serial number to a string.
  354. //
  355. RtlPrintToString(SerialNumber,
  356. sizeof(SerialNumber),
  357. CharacterEncodingAscii,
  358. "%08X%08X",
  359. BoardInformation.SerialMessage.SerialNumber[1],
  360. BoardInformation.SerialMessage.SerialNumber[0]);
  361. RtlCopyMemory(EfiRpi2SmbiosSystemInformation.Uuid,
  362. BoardInformation.SerialMessage.SerialNumber,
  363. sizeof(BoardInformation.SerialMessage.SerialNumber));
  364. //
  365. // Convert the model and revision to a string.
  366. //
  367. RtlPrintToString(Version,
  368. sizeof(Version),
  369. CharacterEncodingAscii,
  370. "Rev %08X",
  371. BoardInformation.RevisionMessage.Revision);
  372. //
  373. // Generate the product name based on the revision.
  374. //
  375. Revision = NULL;
  376. RevisionCount = sizeof(EfiRpi2Revisions) / sizeof(EfiRpi2Revisions[0]);
  377. for (Index = 0; Index < RevisionCount; Index += 1) {
  378. if (EfiRpi2Revisions[Index].Revision ==
  379. BoardInformation.RevisionMessage.Revision) {
  380. Revision = &(EfiRpi2Revisions[Index]);
  381. break;
  382. }
  383. }
  384. if (Revision == NULL) {
  385. ProductName = RPI2_SMBIOS_SYSTEM_PRODUCT_NAME;
  386. } else {
  387. RtlPrintToString(ProductBuffer,
  388. sizeof(ProductBuffer),
  389. CharacterEncodingAscii,
  390. "%s %s",
  391. RPI2_SMBIOS_SYSTEM_PRODUCT_NAME,
  392. Revision->Name);
  393. ProductName = ProductBuffer;
  394. }
  395. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosBiosInformation,
  396. RPI2_SMBIOS_BIOS_VENDOR,
  397. RPI2_FIRMWARE_VERSION_STRING,
  398. RPI2_FIRMWARE_VERSION_DATE,
  399. NULL);
  400. if (EFI_ERROR(Status)) {
  401. return Status;
  402. }
  403. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosSystemInformation,
  404. RPI2_SMBIOS_SYSTEM_MANUFACTURER,
  405. ProductName,
  406. Version,
  407. SerialNumber,
  408. NULL);
  409. if (EFI_ERROR(Status)) {
  410. return Status;
  411. }
  412. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosModuleInformation,
  413. RPI2_SMBIOS_MODULE_MANUFACTURER,
  414. ProductName,
  415. NULL);
  416. if (EFI_ERROR(Status)) {
  417. return Status;
  418. }
  419. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosEnclosure, NULL);
  420. if (EFI_ERROR(Status)) {
  421. return Status;
  422. }
  423. ProcessorPart = "";
  424. if (Revision != NULL) {
  425. ProcessorPart = Revision->ProcessorPart;
  426. }
  427. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosProcessorInformation,
  428. RPI2_SMBIOS_PROCESSOR_MANUFACTURER,
  429. SerialNumber,
  430. ProcessorPart,
  431. NULL);
  432. if (EFI_ERROR(Status)) {
  433. return Status;
  434. }
  435. Status = EfiSmbiosAddStructure(&EfiRpi2SmbiosL1Cache, NULL);
  436. if (EFI_ERROR(Status)) {
  437. return Status;
  438. }
  439. return EFI_SUCCESS;
  440. }
  441. //
  442. // --------------------------------------------------------- Internal Functions
  443. //