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