]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
DynamicTablesPkg: Add OEM Info
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSpcrLibArm / SpcrGenerator.c
CommitLineData
9123b687
SM
1/** @file\r
2 SPCR Table Generator\r
3\r
4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 @par Reference(s):\r
14 - Microsoft Serial Port Console Redirection Table\r
15 Specification - Version 1.03 - August 10, 2015.\r
16\r
17**/\r
18\r
19#include <IndustryStandard/DebugPort2Table.h>\r
20#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>\r
21#include <Library/AcpiLib.h>\r
22#include <Library/DebugLib.h>\r
23#include <Protocol/AcpiTable.h>\r
24\r
25// Module specific include files.\r
26#include <AcpiTableGenerator.h>\r
27#include <ConfigurationManagerObject.h>\r
28#include <ConfigurationManagerHelper.h>\r
29#include <Library/TableHelperLib.h>\r
30#include <Protocol/ConfigurationManagerProtocol.h>\r
31\r
32/** ARM standard SPCR Table Generator\r
33\r
34 Constructs the SPCR table for PL011 or SBSA UART peripherals.\r
35\r
36Requirements:\r
37 The following Configuration Manager Object(s) are required by\r
38 this Generator:\r
39 - EArmObjSerialConsolePortInfo\r
40\r
41NOTE: This implementation ignores the possibility that the Serial settings may\r
42 be modified from the UEFI Shell. A more complex handler would be needed\r
43 to (e.g.) recover serial port settings from the UART, or non-volatile\r
44 storage.\r
45*/\r
46\r
47#pragma pack(1)\r
48\r
49/** This macro defines the no flow control option.\r
50*/\r
51#define SPCR_FLOW_CONTROL_NONE 0\r
52\r
53/**A template for generating the SPCR Table.\r
54\r
55 Note: fields marked "{Template}" will be updated dynamically.\r
56*/\r
57STATIC\r
58EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {\r
59 ACPI_HEADER (\r
60 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
61 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,\r
62 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION\r
63 ),\r
64 0, // {Template}: Serial Port Subtype\r
65 {\r
66 EFI_ACPI_RESERVED_BYTE,\r
67 EFI_ACPI_RESERVED_BYTE,\r
68 EFI_ACPI_RESERVED_BYTE\r
69 },\r
70 ARM_GAS32 (0), // {Template}: Serial Port Base Address\r
71 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,\r
72 0, // Not used on ARM\r
73 0, // {Template}: Serial Port Interrupt\r
74 0, // {Template}: Serial Port Baudrate\r
75 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,\r
76 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,\r
77 SPCR_FLOW_CONTROL_NONE,\r
78 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,\r
79 EFI_ACPI_RESERVED_BYTE,\r
80 0xFFFF,\r
81 0xFFFF,\r
82 0x00,\r
83 0x00,\r
84 0x00,\r
85 0x00000000,\r
86 0x00,\r
87 EFI_ACPI_RESERVED_DWORD\r
88};\r
89\r
90#pragma pack()\r
91\r
92/** This macro expands to a function that retrieves the Serial\r
93 Port Information from the Configuration Manager.\r
94*/\r
95GET_OBJECT_LIST (\r
96 EObjNameSpaceArm,\r
97 EArmObjSerialConsolePortInfo,\r
98 CM_ARM_SERIAL_PORT_INFO\r
99 )\r
100\r
101/** Construct the SPCR ACPI table.\r
102\r
103 This function invokes the Configuration Manager protocol interface\r
104 to get the required hardware information for generating the ACPI\r
105 table.\r
106\r
107 If this function allocates any resources then they must be freed\r
108 in the FreeXXXXTableResources function.\r
109\r
110 @param [in] This Pointer to the table generator.\r
111 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
112 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
113 Protocol Interface.\r
114 @param [out] Table Pointer to the constructed ACPI Table.\r
115\r
116 @retval EFI_SUCCESS Table generated successfully.\r
117 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
118 @retval EFI_NOT_FOUND The required object was not found.\r
119 @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the\r
120 Configuration Manager.\r
121 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
122 Manager is less than the Object size for the\r
123 requested object.\r
124**/\r
125STATIC\r
126EFI_STATUS\r
127EFIAPI\r
128BuildSpcrTable (\r
129 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
130 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
131 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
132 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;\r
137\r
138 ASSERT (This != NULL);\r
139 ASSERT (AcpiTableInfo != NULL);\r
140 ASSERT (CfgMgrProtocol != NULL);\r
141 ASSERT (Table != NULL);\r
142 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
143 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
144\r
145 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
146 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
147 DEBUG ((\r
148 DEBUG_ERROR,\r
149 "ERROR: SPCR: Requested table revision = %d, is not supported."\r
150 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
151 AcpiTableInfo->AcpiTableRevision,\r
152 This->MinAcpiTableRevision,\r
153 This->AcpiTableRevision\r
154 ));\r
155 return EFI_INVALID_PARAMETER;\r
156 }\r
157\r
158 *Table = NULL;\r
159\r
160 Status = GetEArmObjSerialConsolePortInfo (\r
161 CfgMgrProtocol,\r
162 CM_NULL_TOKEN,\r
163 &SerialPortInfo,\r
164 NULL\r
165 );\r
166 if (EFI_ERROR (Status)) {\r
167 DEBUG ((\r
168 DEBUG_ERROR,\r
169 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",\r
170 Status\r
171 ));\r
172 goto error_handler;\r
173 }\r
174\r
175 if (SerialPortInfo->BaseAddress == 0) {\r
176 Status = EFI_INVALID_PARAMETER;\r
177 DEBUG ((\r
178 DEBUG_ERROR,\r
179 "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",\r
180 SerialPortInfo->BaseAddress\r
181 ));\r
182 goto error_handler;\r
183 }\r
184\r
185 if ((SerialPortInfo->PortSubtype !=\r
186 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&\r
187 (SerialPortInfo->PortSubtype !=\r
188 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&\r
189 (SerialPortInfo->PortSubtype !=\r
190 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&\r
191 (SerialPortInfo->PortSubtype !=\r
0692ef87
AS
192 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550) &&\r
193 (SerialPortInfo->PortSubtype !=\r
9123b687
SM
194 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {\r
195 Status = EFI_INVALID_PARAMETER;\r
196 DEBUG ((\r
197 DEBUG_ERROR,\r
198 "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n",\r
199 SerialPortInfo->PortSubtype\r
200 ));\r
201 goto error_handler;\r
202 }\r
203\r
204 DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));\r
205 DEBUG ((DEBUG_INFO, " UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));\r
206 DEBUG ((DEBUG_INFO, " Clock = %d\n", SerialPortInfo->Clock));\r
207 DEBUG ((DEBUG_INFO, " Baudrate = %ld\n", SerialPortInfo->BaudRate));\r
208 DEBUG ((DEBUG_INFO, " Interrupt = %d\n", SerialPortInfo->Interrupt));\r
209\r
210 Status = AddAcpiHeader (\r
211 CfgMgrProtocol,\r
212 This,\r
213 (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,\r
c788bdab 214 AcpiTableInfo,\r
9123b687
SM
215 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)\r
216 );\r
217 if (EFI_ERROR (Status)) {\r
218 DEBUG ((\r
219 DEBUG_ERROR,\r
220 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",\r
221 Status\r
222 ));\r
223 goto error_handler;\r
224 }\r
225\r
226 // Update the serial port subtype\r
227 AcpiSpcr.InterfaceType = SerialPortInfo->PortSubtype;\r
228\r
229 // Update the base address\r
230 AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;\r
231\r
232 // Update the UART interrupt\r
233 AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;\r
234\r
235 switch (SerialPortInfo->BaudRate) {\r
236 case 9600:\r
237 AcpiSpcr.BaudRate =\r
238 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;\r
239 break;\r
240 case 19200:\r
241 AcpiSpcr.BaudRate =\r
242 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;\r
243 break;\r
244 case 57600:\r
245 AcpiSpcr.BaudRate =\r
246 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;\r
247 break;\r
248 case 115200:\r
249 AcpiSpcr.BaudRate =\r
250 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;\r
251 break;\r
252 default:\r
253 Status = EFI_UNSUPPORTED;\r
254 DEBUG ((\r
255 DEBUG_ERROR,\r
256 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",\r
257 SerialPortInfo->BaudRate,\r
258 Status\r
259 ));\r
260 goto error_handler;\r
261 } // switch\r
262\r
263 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;\r
264\r
265error_handler:\r
266 return Status;\r
267}\r
268\r
269/** This macro defines the SPCR Table Generator revision.\r
270*/\r
271#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
272\r
273/** The interface for the SPCR Table Generator.\r
274*/\r
275STATIC\r
276CONST\r
277ACPI_TABLE_GENERATOR SpcrGenerator = {\r
278 // Generator ID\r
279 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),\r
280 // Generator Description\r
281 L"ACPI.STD.SPCR.GENERATOR",\r
282 // ACPI Table Signature\r
283 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
284 // ACPI Table Revision supported by this Generator\r
285 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
286 // Minimum supported ACPI Table Revision\r
287 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
288 // Creator ID\r
289 TABLE_GENERATOR_CREATOR_ID_ARM,\r
290 // Creator Revision\r
291 SPCR_GENERATOR_REVISION,\r
292 // Build Table function\r
293 BuildSpcrTable,\r
294 // No additional resources are allocated by the generator.\r
295 // Hence the Free Resource function is not required.\r
296 NULL,\r
297 // Extended build function not needed\r
298 NULL,\r
299 // Extended build function not implemented by the generator.\r
300 // Hence extended free resource function is not required.\r
301 NULL\r
302};\r
303\r
304/** Register the Generator with the ACPI Table Factory.\r
305\r
306 @param [in] ImageHandle The handle to the image.\r
307 @param [in] SystemTable Pointer to the System Table.\r
308\r
309 @retval EFI_SUCCESS The Generator is registered.\r
310 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
311 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
312 is already registered.\r
313**/\r
314EFI_STATUS\r
315EFIAPI\r
316AcpiSpcrLibConstructor (\r
317 IN CONST EFI_HANDLE ImageHandle,\r
318 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
319 )\r
320{\r
321 EFI_STATUS Status;\r
322 Status = RegisterAcpiTableGenerator (&SpcrGenerator);\r
323 DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));\r
324 ASSERT_EFI_ERROR (Status);\r
325 return Status;\r
326}\r
327\r
328/** Deregister the Generator from the ACPI Table Factory.\r
329\r
330 @param [in] ImageHandle The handle to the image.\r
331 @param [in] SystemTable Pointer to the System Table.\r
332\r
333 @retval EFI_SUCCESS The Generator is deregistered.\r
334 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
335 @retval EFI_NOT_FOUND The Generator is not registered.\r
336**/\r
337EFI_STATUS\r
338EFIAPI\r
339AcpiSpcrLibDestructor (\r
340 IN CONST EFI_HANDLE ImageHandle,\r
341 IN EFI_SYSTEM_TABLE * CONST SystemTable\r
342 )\r
343{\r
344 EFI_STATUS Status;\r
345 Status = DeregisterAcpiTableGenerator (&SpcrGenerator);\r
346 DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status));\r
347 ASSERT_EFI_ERROR (Status);\r
348 return Status;\r
349}\r