smbios.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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.
  7. Author:
  8. Chris Stevens 8-Jan-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 "rpifw.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 RPI_FIRMWARE_VERSION_MAJOR 1
  31. #define RPI_FIRMWARE_VERSION_MINOR 1
  32. #define RPI_FIRMWARE_VERSION_STRING "1.1"
  33. #define RPI_FIRMWARE_VERSION_DATE "05/06/2016"
  34. #define RPI_SMBIOS_BIOS_VENDOR "Minoca Corp"
  35. #define RPI_SMBIOS_SYSTEM_MANUFACTURER "Raspberry Pi Foundation"
  36. #define RPI_SMBIOS_SYSTEM_PRODUCT_NAME "Raspberry Pi"
  37. #define RPI_SMBIOS_MODULE_MANUFACTURER "Raspberry Pi Foundation"
  38. #define RPI_SMBIOS_MODULE_PRODUCT "Raspberry Pi"
  39. #define RPI_SMBIOS_PROCESSOR_MANUFACTURER "Broadcom"
  40. #define RPI_SMBIOS_PROCESSOR_PART "BCM2835"
  41. #define RPI_SMBIOS_PROCESSOR_EXTERNAL_CLOCK 250
  42. #define RPI_SMBIOS_PROCESSOR_CORE_COUNT 1
  43. #define RPI_SMBIOS_CACHE_L1_SIZE 16
  44. #define HERTZ_PER_MEGAHERTZ 1000000ULL
  45. //
  46. // ------------------------------------------------------ Data Type Definitions
  47. //
  48. /*++
  49. Structure Description:
  50. This structure defines the data necessary to query the BCM2709 video core
  51. for SMBIOS related information.
  52. Members:
  53. Header - Stores a header that defines the total size of the messages being
  54. sent to and received from the mailbox.
  55. RevisionMessage - Stores a message indicating that the board's revision is
  56. being queried. Contains the revision on return.
  57. SerialMessage - Stores a messagin indicating that the board's serial number
  58. is being queried. Contains the serial number on return.
  59. ArmClockRate - Stores a message requesting the ARM core's clock rate.
  60. ArmMaxClockRate - Stores a message requesting the ARM core's maximum clock
  61. rate.
  62. EndTag - Stores the tag to denote the end of the mailbox message.
  63. --*/
  64. typedef struct _EFI_BCM2709_GET_SMBIOS_INFORMATION {
  65. BCM2709_MAILBOX_HEADER Header;
  66. BCM2709_MAILBOX_BOARD_REVISION RevisionMessage;
  67. BCM2709_MAILBOX_BOARD_SERIAL_NUMBER SerialMessage;
  68. BCM2709_MAILBOX_GET_CLOCK_RATE ArmClockRate;
  69. BCM2709_MAILBOX_GET_CLOCK_RATE ArmMaxClockRate;
  70. UINT32 EndTag;
  71. } EFI_BCM2709_GET_SMBIOS_INFORMATION, *PEFI_BCM2709_GET_SMBIOS_INFORMATION;
  72. /*++
  73. Structure Description:
  74. This structure defines a Raspberry Pi revision.
  75. Members:
  76. Revision - Stores the Raspberry Pi revision number.
  77. Name - Stores the friendly name of the revision.
  78. --*/
  79. typedef struct _RPI_REVISION {
  80. UINT32 Revision;
  81. CHAR8 *Name;
  82. } RPI_REVISION, *PRPI_REVISION;
  83. //
  84. // ----------------------------------------------- Internal Function Prototypes
  85. //
  86. //
  87. // -------------------------------------------------------------------- Globals
  88. //
  89. SMBIOS_BIOS_INFORMATION EfiRpiSmbiosBiosInformation = {
  90. {
  91. SmbiosBiosInformation,
  92. sizeof(SMBIOS_BIOS_INFORMATION),
  93. 0x0100
  94. },
  95. 1,
  96. 2,
  97. 0,
  98. 3,
  99. 0,
  100. SMBIOS_BIOS_CHARACTERISTIC_UNSUPPORTED,
  101. 0,
  102. RPI_FIRMWARE_VERSION_MAJOR,
  103. RPI_FIRMWARE_VERSION_MINOR,
  104. 0,
  105. 0
  106. };
  107. SMBIOS_SYSTEM_INFORMATION EfiRpiSmbiosSystemInformation = {
  108. {
  109. SmbiosSystemInformation,
  110. sizeof(SMBIOS_SYSTEM_INFORMATION),
  111. 0x0101
  112. },
  113. 1,
  114. 2,
  115. 3,
  116. 4,
  117. {0},
  118. SMBIOS_SYSTEM_WAKEUP_UNKNOWN,
  119. 3,
  120. 2
  121. };
  122. SMBIOS_MODULE_INFORMATION EfiRpiSmbiosModuleInformation = {
  123. {
  124. SmbiosModuleInformation,
  125. sizeof(SMBIOS_MODULE_INFORMATION),
  126. 0x0102
  127. },
  128. 1,
  129. 2,
  130. 0,
  131. 0,
  132. 0,
  133. SMBIOS_MODULE_MOTHERBOARD,
  134. 0,
  135. 0x0104,
  136. SMBIOS_MODULE_TYPE_MOTHERBOARD,
  137. 0
  138. };
  139. SMBIOS_ENCLOSURE EfiRpiSmbiosEnclosure = {
  140. {
  141. SmbiosSystemEnclosure,
  142. sizeof(SMBIOS_ENCLOSURE),
  143. 0x0104
  144. },
  145. 0,
  146. SMBIOS_ENCLOSURE_TYPE_UNKNOWN,
  147. 0,
  148. 0,
  149. 0,
  150. SMBIOS_ENCLOSURE_STATE_UNKNOWN,
  151. SMBIOS_ENCLOSURE_STATE_UNKNOWN,
  152. SMBIOS_ENCLOSURE_SECURITY_STATE_UNKNOWN,
  153. 0,
  154. 0,
  155. 0,
  156. 0,
  157. 0,
  158. 0
  159. };
  160. SMBIOS_PROCESSOR_INFORMATION EfiRpiSmbiosProcessorInformation = {
  161. {
  162. SmbiosProcessorInformation,
  163. sizeof(SMBIOS_PROCESSOR_INFORMATION),
  164. 0x0105
  165. },
  166. 0,
  167. SMBIOS_PROCESSOR_TYPE_CENTRAL_PROCESSOR,
  168. 0x2,
  169. 1,
  170. 0,
  171. 0,
  172. 0,
  173. RPI_SMBIOS_PROCESSOR_EXTERNAL_CLOCK,
  174. 0,
  175. 0,
  176. SMBIOS_PROCESSOR_STATUS_ENABLED,
  177. 0,
  178. 0x0106,
  179. 0xFFFF,
  180. 0xFFFF,
  181. 2,
  182. 0,
  183. 3,
  184. RPI_SMBIOS_PROCESSOR_CORE_COUNT,
  185. 0,
  186. SMBIOS_PROCESSOR_CHARACTERISTIC_UNKNOWN,
  187. 0
  188. };
  189. SMBIOS_CACHE_INFORMATION EfiRpiSmbiosL1Cache = {
  190. {
  191. SmbiosCacheInformation,
  192. sizeof(SMBIOS_CACHE_INFORMATION),
  193. 0x0106
  194. },
  195. 0,
  196. SMBIOS_CACHE_ENABLED | SMBIOS_CACHE_WRITE_BACK,
  197. RPI_SMBIOS_CACHE_L1_SIZE,
  198. RPI_SMBIOS_CACHE_L1_SIZE,
  199. SMBIOS_CACHE_SRAM_UNKNOWN,
  200. SMBIOS_CACHE_SRAM_UNKNOWN,
  201. 0,
  202. SMBIOS_CACHE_ERROR_CORRECTION_NONE,
  203. SMBIOS_CACHE_TYPE_DATA,
  204. SMBIOS_CACHE_ASSOCIATIVITY_4_WAY_SET
  205. };
  206. EFI_BCM2709_GET_SMBIOS_INFORMATION EfiRpiBoardInformationTemplate = {
  207. {
  208. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION),
  209. 0
  210. },
  211. {
  212. {
  213. BCM2709_MAILBOX_TAG_GET_BOARD_REVISION,
  214. sizeof(UINT32),
  215. 0
  216. },
  217. 0
  218. },
  219. {
  220. {
  221. BCM2709_MAILBOX_TAG_GET_BOARD_SERIAL,
  222. sizeof(UINT32) * 2,
  223. 0
  224. },
  225. {0, 0}
  226. },
  227. {
  228. {
  229. BCM2709_MAILBOX_TAG_GET_CLOCK_RATE,
  230. sizeof(UINT32) + sizeof(UINT32),
  231. sizeof(UINT32)
  232. },
  233. BCM2709_MAILBOX_CLOCK_ID_ARM,
  234. 0
  235. },
  236. {
  237. {
  238. BCM2709_MAILBOX_TAG_GET_CLOCK_MAX_RATE,
  239. sizeof(UINT32) + sizeof(UINT32),
  240. sizeof(UINT32)
  241. },
  242. BCM2709_MAILBOX_CLOCK_ID_ARM,
  243. 0
  244. },
  245. 0
  246. };
  247. RPI_REVISION EfiRpiRevisions[] = {
  248. {0x00000001, "1 Model B (Beta)"},
  249. {0x00000002, "1 Model B Rev 1.0"},
  250. {0x00000003, "1 Model B Rev 1.0 (ECN0001)"},
  251. {0x00000004, "1 Model B Rev 2.0"},
  252. {0x00000005, "1 Model B Rev 2.0"},
  253. {0x00000006, "1 Model B Rev 2.0"},
  254. {0x00000007, "1 Model A Rev 2.0"},
  255. {0x00000008, "1 Model A Rev 2.0"},
  256. {0x00000009, "1 Model A Rev 2.0"},
  257. {0x0000000D, "1 Model B Rev 2.0"},
  258. {0x0000000E, "1 Model B Rev 2.0"},
  259. {0x0000000F, "1 Model B Rev 2.0"},
  260. {0x00000010, "1 Model B+ Rev 1.0"},
  261. {0x00000011, "Compute Module Rev 1.0"},
  262. {0x00000012, "1 Model A+ Rev 1.0"},
  263. {0x00000013, "1 Model B+ Rev 1.2"},
  264. {0x00900092, "Zero Rev 1.2"}
  265. };
  266. //
  267. // ------------------------------------------------------------------ Functions
  268. //
  269. EFI_STATUS
  270. EfipRpiCreateSmbiosTables (
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. This routine creates the SMBIOS tables.
  276. Arguments:
  277. None.
  278. Return Value:
  279. EFI Status code.
  280. --*/
  281. {
  282. EFI_BCM2709_GET_SMBIOS_INFORMATION BoardInformation;
  283. UINT32 ExpectedLength;
  284. UINT32 Index;
  285. UINT32 Length;
  286. CHAR8 ProductBuffer[64];
  287. CHAR8 *ProductName;
  288. PRPI_REVISION Revision;
  289. UINT32 RevisionCount;
  290. CHAR8 SerialNumber[17];
  291. EFI_STATUS Status;
  292. CHAR8 Version[13];
  293. //
  294. // Query the BMC2835 mailbox to get version information and a serial number.
  295. //
  296. EfiCopyMem(&BoardInformation,
  297. &EfiRpiBoardInformationTemplate,
  298. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION));
  299. Status = EfipBcm2709MailboxSendCommand(
  300. BCM2709_MAILBOX_PROPERTIES_CHANNEL,
  301. &BoardInformation,
  302. sizeof(EFI_BCM2709_GET_SMBIOS_INFORMATION),
  303. FALSE);
  304. if (EFI_ERROR(Status)) {
  305. return Status;
  306. }
  307. Length = BoardInformation.RevisionMessage.TagHeader.Length;
  308. ExpectedLength = sizeof(BCM2709_MAILBOX_BOARD_REVISION) -
  309. sizeof(BCM2709_MAILBOX_TAG);
  310. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  311. return EFI_DEVICE_ERROR;
  312. }
  313. Length = BoardInformation.SerialMessage.TagHeader.Length;
  314. ExpectedLength = sizeof(BCM2709_MAILBOX_BOARD_SERIAL_NUMBER) -
  315. sizeof(BCM2709_MAILBOX_TAG);
  316. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  317. return EFI_DEVICE_ERROR;
  318. }
  319. Length = BoardInformation.ArmClockRate.TagHeader.Length;
  320. ExpectedLength = sizeof(BCM2709_MAILBOX_GET_CLOCK_RATE) -
  321. sizeof(BCM2709_MAILBOX_TAG);
  322. if (BCM2709_MAILBOX_CHECK_TAG_LENGTH(Length, ExpectedLength) == FALSE) {
  323. return EFI_DEVICE_ERROR;
  324. }
  325. Length = BoardInformation.ArmMaxClockRate.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. //
  332. // Update the clock information.
  333. //
  334. EfiRpiSmbiosProcessorInformation.MaxSpeed =
  335. BoardInformation.ArmMaxClockRate.Rate / HERTZ_PER_MEGAHERTZ;
  336. EfiRpiSmbiosProcessorInformation.CurrentSpeed =
  337. BoardInformation.ArmClockRate.Rate / HERTZ_PER_MEGAHERTZ;
  338. //
  339. // Convert the serial number to a string.
  340. //
  341. RtlPrintToString(SerialNumber,
  342. sizeof(SerialNumber),
  343. CharacterEncodingAscii,
  344. "%08X%08X",
  345. BoardInformation.SerialMessage.SerialNumber[1],
  346. BoardInformation.SerialMessage.SerialNumber[0]);
  347. RtlCopyMemory(EfiRpiSmbiosSystemInformation.Uuid,
  348. BoardInformation.SerialMessage.SerialNumber,
  349. sizeof(BoardInformation.SerialMessage.SerialNumber));
  350. //
  351. // Convert the revision to a string.
  352. //
  353. RtlPrintToString(Version,
  354. sizeof(Version),
  355. CharacterEncodingAscii,
  356. "Rev %08X",
  357. BoardInformation.RevisionMessage.Revision);
  358. //
  359. // Generate the product name based on the revision.
  360. //
  361. Revision = NULL;
  362. RevisionCount = sizeof(EfiRpiRevisions) / sizeof(EfiRpiRevisions[0]);
  363. for (Index = 0; Index < RevisionCount; Index += 1) {
  364. if (EfiRpiRevisions[Index].Revision ==
  365. BoardInformation.RevisionMessage.Revision) {
  366. Revision = &(EfiRpiRevisions[Index]);
  367. break;
  368. }
  369. }
  370. if (Revision == NULL) {
  371. ProductName = RPI_SMBIOS_SYSTEM_PRODUCT_NAME;
  372. } else {
  373. RtlPrintToString(ProductBuffer,
  374. sizeof(ProductBuffer),
  375. CharacterEncodingAscii,
  376. "%s %s",
  377. RPI_SMBIOS_SYSTEM_PRODUCT_NAME,
  378. Revision->Name);
  379. ProductName = ProductBuffer;
  380. }
  381. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosBiosInformation,
  382. RPI_SMBIOS_BIOS_VENDOR,
  383. RPI_FIRMWARE_VERSION_STRING,
  384. RPI_FIRMWARE_VERSION_DATE,
  385. NULL);
  386. if (EFI_ERROR(Status)) {
  387. return Status;
  388. }
  389. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosSystemInformation,
  390. RPI_SMBIOS_SYSTEM_MANUFACTURER,
  391. ProductName,
  392. Version,
  393. SerialNumber,
  394. NULL);
  395. if (EFI_ERROR(Status)) {
  396. return Status;
  397. }
  398. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosModuleInformation,
  399. RPI_SMBIOS_MODULE_MANUFACTURER,
  400. ProductName,
  401. NULL);
  402. if (EFI_ERROR(Status)) {
  403. return Status;
  404. }
  405. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosEnclosure, NULL);
  406. if (EFI_ERROR(Status)) {
  407. return Status;
  408. }
  409. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosProcessorInformation,
  410. RPI_SMBIOS_PROCESSOR_MANUFACTURER,
  411. SerialNumber,
  412. RPI_SMBIOS_PROCESSOR_PART,
  413. NULL);
  414. if (EFI_ERROR(Status)) {
  415. return Status;
  416. }
  417. Status = EfiSmbiosAddStructure(&EfiRpiSmbiosL1Cache, NULL);
  418. if (EFI_ERROR(Status)) {
  419. return Status;
  420. }
  421. return EFI_SUCCESS;
  422. }
  423. //
  424. // --------------------------------------------------------- Internal Functions
  425. //