]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
DynamicTablesPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSpcrLibArm / SpcrGenerator.c
1 /** @file
2 SPCR Table Generator
3
4 Copyright (c) 2017 - 2019, 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 sybtype 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 // Update the serial port subtype
221 AcpiSpcr.InterfaceType = SerialPortInfo->PortSubtype;
222
223 // Update the base address
224 AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
225
226 // Update the UART interrupt
227 AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
228
229 switch (SerialPortInfo->BaudRate) {
230 case 9600:
231 AcpiSpcr.BaudRate =
232 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
233 break;
234 case 19200:
235 AcpiSpcr.BaudRate =
236 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
237 break;
238 case 57600:
239 AcpiSpcr.BaudRate =
240 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
241 break;
242 case 115200:
243 AcpiSpcr.BaudRate =
244 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
245 break;
246 default:
247 Status = EFI_UNSUPPORTED;
248 DEBUG ((
249 DEBUG_ERROR,
250 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
251 SerialPortInfo->BaudRate,
252 Status
253 ));
254 goto error_handler;
255 } // switch
256
257 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
258
259 error_handler:
260 return Status;
261 }
262
263 /** This macro defines the SPCR Table Generator revision.
264 */
265 #define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
266
267 /** The interface for the SPCR Table Generator.
268 */
269 STATIC
270 CONST
271 ACPI_TABLE_GENERATOR SpcrGenerator = {
272 // Generator ID
273 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),
274 // Generator Description
275 L"ACPI.STD.SPCR.GENERATOR",
276 // ACPI Table Signature
277 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
278 // ACPI Table Revision supported by this Generator
279 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
280 // Minimum supported ACPI Table Revision
281 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
282 // Creator ID
283 TABLE_GENERATOR_CREATOR_ID_ARM,
284 // Creator Revision
285 SPCR_GENERATOR_REVISION,
286 // Build Table function
287 BuildSpcrTable,
288 // No additional resources are allocated by the generator.
289 // Hence the Free Resource function is not required.
290 NULL,
291 // Extended build function not needed
292 NULL,
293 // Extended build function not implemented by the generator.
294 // Hence extended free resource function is not required.
295 NULL
296 };
297
298 /** Register the Generator with the ACPI Table Factory.
299
300 @param [in] ImageHandle The handle to the image.
301 @param [in] SystemTable Pointer to the System Table.
302
303 @retval EFI_SUCCESS The Generator is registered.
304 @retval EFI_INVALID_PARAMETER A parameter is invalid.
305 @retval EFI_ALREADY_STARTED The Generator for the Table ID
306 is already registered.
307 **/
308 EFI_STATUS
309 EFIAPI
310 AcpiSpcrLibConstructor (
311 IN CONST EFI_HANDLE ImageHandle,
312 IN EFI_SYSTEM_TABLE * CONST SystemTable
313 )
314 {
315 EFI_STATUS Status;
316 Status = RegisterAcpiTableGenerator (&SpcrGenerator);
317 DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
318 ASSERT_EFI_ERROR (Status);
319 return Status;
320 }
321
322 /** Deregister the Generator from the ACPI Table Factory.
323
324 @param [in] ImageHandle The handle to the image.
325 @param [in] SystemTable Pointer to the System Table.
326
327 @retval EFI_SUCCESS The Generator is deregistered.
328 @retval EFI_INVALID_PARAMETER A parameter is invalid.
329 @retval EFI_NOT_FOUND The Generator is not registered.
330 **/
331 EFI_STATUS
332 EFIAPI
333 AcpiSpcrLibDestructor (
334 IN CONST EFI_HANDLE ImageHandle,
335 IN EFI_SYSTEM_TABLE * CONST SystemTable
336 )
337 {
338 EFI_STATUS Status;
339 Status = DeregisterAcpiTableGenerator (&SpcrGenerator);
340 DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status));
341 ASSERT_EFI_ERROR (Status);
342 return Status;
343 }