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