TianoCore EDK2 master
Loading...
Searching...
No Matches
SpcrGenerator.c
Go to the documentation of this file.
1
16#include <Library/AcpiLib.h>
17#include <Library/DebugLib.h>
19#include <Protocol/AcpiTable.h>
20
21// Module specific include files.
22#include <AcpiTableGenerator.h>
28
44#pragma pack(1)
45
48#define NAME_STR_SPCR_PORT "COM1"
49
52#define UID_SPCR_PORT 1
53
56#define SPCR_FLOW_CONTROL_NONE 0
57
68 ),
69 0, // {Template}: Serial Port Subtype
70 {
71 EFI_ACPI_RESERVED_BYTE,
72 EFI_ACPI_RESERVED_BYTE,
73 EFI_ACPI_RESERVED_BYTE
74 },
75 ARM_GAS32 (0), // {Template}: Serial Port Base Address
77 0, // Not used on ARM
78 0, // {Template}: Serial Port Interrupt
79 0, // {Template}: Serial Port Baudrate
80 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
81 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
83 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,
84 EFI_ACPI_RESERVED_BYTE,
85 0xFFFF,
86 0xFFFF,
87 0x00,
88 0x00,
89 0x00,
90 0x00000000,
91 0x00,
92 EFI_ACPI_RESERVED_DWORD
93};
94
95#pragma pack()
96
104 )
105
106
119STATIC
121EFIAPI
122FreeSpcrTableEx (
127 IN CONST UINTN TableCount
128 )
129{
130 EFI_STATUS Status;
131 EFI_ACPI_DESCRIPTION_HEADER **TableList;
132
133 ASSERT (This != NULL);
134 ASSERT (AcpiTableInfo != NULL);
135 ASSERT (CfgMgrProtocol != NULL);
136 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
137 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
138
139 if ((Table == NULL) ||
140 (*Table == NULL) ||
141 (TableCount != 2))
142 {
143 DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n"));
144 return EFI_INVALID_PARAMETER;
145 }
146
147 TableList = *Table;
148
149 if ((TableList[1] == NULL) ||
150 (TableList[1]->Signature !=
152 {
153 DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n"));
154 return EFI_INVALID_PARAMETER;
155 }
156
157 // Only need to free the SSDT table at index 1. The SPCR table is static.
158 Status = FreeSsdtSerialPortTable (TableList[1]);
159 ASSERT_EFI_ERROR (Status);
160
161 // Free the table list.
162 FreePool (*Table);
163
164 return Status;
165}
166
192STATIC
194EFIAPI
200 OUT UINTN *CONST TableCount
201 )
202{
203 EFI_STATUS Status;
204 CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo;
205 UINT32 SerialPortCount;
206 EFI_ACPI_DESCRIPTION_HEADER **TableList;
207
208 ASSERT (This != NULL);
209 ASSERT (AcpiTableInfo != NULL);
210 ASSERT (CfgMgrProtocol != NULL);
211 ASSERT (Table != NULL);
212 ASSERT (TableCount != NULL);
213 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
214 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
215
216 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
217 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
218 {
219 DEBUG ((
220 DEBUG_ERROR,
221 "ERROR: SPCR: Requested table revision = %d, is not supported."
222 "Supported table revision: Minimum = %d, Maximum = %d\n",
223 AcpiTableInfo->AcpiTableRevision,
224 This->MinAcpiTableRevision,
225 This->AcpiTableRevision
226 ));
227 return EFI_INVALID_PARAMETER;
228 }
229
230 *Table = NULL;
231
232 Status = GetEArchCommonObjConsolePortInfo (
233 CfgMgrProtocol,
235 &SerialPortInfo,
236 &SerialPortCount
237 );
238 if (EFI_ERROR (Status)) {
239 DEBUG ((
240 DEBUG_ERROR,
241 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
242 Status
243 ));
244 return Status;
245 }
246
247 if (SerialPortCount == 0) {
248 DEBUG ((
249 DEBUG_ERROR,
250 "ERROR: SPCR: Serial port information not found. Status = %r\n",
251 EFI_NOT_FOUND
252 ));
253 return EFI_NOT_FOUND;
254 }
255
256 // Validate the SerialPort info. Only one SPCR port can be described.
257 // If platform provides description for multiple SPCR ports, use the
258 // first SPCR port information.
259 Status = ValidateSerialPortInfo (SerialPortInfo, 1);
260 if (EFI_ERROR (Status)) {
261 DEBUG ((
262 DEBUG_ERROR,
263 "ERROR: SPCR: Invalid serial port information. Status = %r\n",
264 Status
265 ));
266 return Status;
267 }
268
269 // Allocate a table to store pointers to the SPCR and SSDT tables.
270 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
272 if (TableList == NULL) {
273 Status = EFI_OUT_OF_RESOURCES;
274 DEBUG ((
275 DEBUG_ERROR,
276 "ERROR: SPCR: Failed to allocate memory for Table List," \
277 " Status = %r\n",
278 Status
279 ));
280 return Status;
281 }
282
283 // Build SPCR table.
284 Status = AddAcpiHeader (
285 CfgMgrProtocol,
286 This,
288 AcpiTableInfo,
290 );
291 if (EFI_ERROR (Status)) {
292 DEBUG ((
293 DEBUG_ERROR,
294 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
295 Status
296 ));
297 goto error_handler;
298 }
299
300 // The SPCR InterfaceType uses the same encoding as that of the
301 // DBG2 table Port Subtype field. However InterfaceType is 8-bit
302 // while the Port Subtype field in the DBG2 table is 16-bit.
303 if ((SerialPortInfo->PortSubtype & 0xFF00) != 0) {
304 Status = EFI_INVALID_PARAMETER;
305 DEBUG ((
306 DEBUG_ERROR,
307 "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",
308 Status
309 ));
310 goto error_handler;
311 }
312
313 // Update the serial port subtype
314 AcpiSpcr.InterfaceType = (UINT8)SerialPortInfo->PortSubtype;
315
316 // Update the base address
317 AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
318
319 // Set the access size
320 if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {
321 Status = EFI_INVALID_PARAMETER;
322 DEBUG ((
323 DEBUG_ERROR,
324 "ERROR: SPCR: Access size must be <= 3 (DWORD). Status = %r\n",
325 Status
326 ));
327 goto error_handler;
328 } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {
329 // 0 Undefined (legacy reasons)
330 // Default to DWORD access size as the access
331 // size field was introduced at a later date
332 // and some ConfigurationManager implementations
333 // may not be providing this field data
334 AcpiSpcr.BaseAddress.AccessSize = EFI_ACPI_6_3_DWORD;
335 } else {
336 AcpiSpcr.BaseAddress.AccessSize = SerialPortInfo->AccessSize;
337 }
338
339 // Update the UART interrupt
340 AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
341
342 switch (SerialPortInfo->BaudRate) {
343 case 9600:
344 AcpiSpcr.BaudRate =
345 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;
346 break;
347 case 19200:
348 AcpiSpcr.BaudRate =
349 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;
350 break;
351 case 57600:
352 AcpiSpcr.BaudRate =
353 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;
354 break;
355 case 115200:
356 AcpiSpcr.BaudRate =
357 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;
358 break;
359 default:
360 Status = EFI_UNSUPPORTED;
361 DEBUG ((
362 DEBUG_ERROR,
363 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
364 SerialPortInfo->BaudRate,
365 Status
366 ));
367 goto error_handler;
368 } // switch
369
370 TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr;
371
372 // Build a SSDT table describing the serial port.
373 Status = BuildSsdtSerialPortTable (
374 AcpiTableInfo,
375 SerialPortInfo,
378 &TableList[1]
379 );
380 if (EFI_ERROR (Status)) {
381 DEBUG ((
382 DEBUG_ERROR,
383 "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n",
384 Status
385 ));
386 goto error_handler;
387 }
388
389 *TableCount = 2;
390 *Table = TableList;
391
392 return Status;
393
394error_handler:
395 if (TableList != NULL) {
396 FreePool (TableList);
397 }
398
399 return Status;
400}
401
404#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
405
408STATIC
409CONST
411 // Generator ID
413 // Generator Description
414 L"ACPI.STD.SPCR.GENERATOR",
415 // ACPI Table Signature
417 // ACPI Table Revision supported by this Generator
419 // Minimum supported ACPI Table Revision
421 // Creator ID
423 // Creator Revision
425 // Build table function. Use the extended version instead.
426 NULL,
427 // Free table function. Use the extended version instead.
428 NULL,
429 // Extended Build table function.
431 // Extended free function.
432 FreeSpcrTableEx
433};
434
446EFIAPI
448 IN EFI_HANDLE ImageHandle,
449 IN EFI_SYSTEM_TABLE *SystemTable
450 )
451{
452 EFI_STATUS Status;
453
455 DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));
456 ASSERT_EFI_ERROR (Status);
457 return Status;
458}
459
470EFIAPI
472 IN EFI_HANDLE ImageHandle,
473 IN EFI_SYSTEM_TABLE *SystemTable
474 )
475{
476 EFI_STATUS Status;
477
479 DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status));
480 ASSERT_EFI_ERROR (Status);
481 return Status;
482}
UINT64 UINTN
#define EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
Definition: Acpi62.h:2936
#define EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
Definition: Acpi63.h:2936
#define EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
Definition: Acpi63.h:2831
EFI_STATUS EFIAPI RegisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
EFI_STATUS EFIAPI DeregisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId)
#define TABLE_GENERATOR_CREATOR_ID
@ EStdAcpiTableIdSpcr
SPCR Generator.
#define ACPI_HEADER(Signature, Type, Revision)
@ EArchCommonObjConsolePortInfo
3 - Serial Console Port Info
#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)
@ EObjNameSpaceArchCommon
Arch Common Objects Namespace.
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC
#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
#define SPCR_GENERATOR_REVISION
STATIC EFI_STATUS EFIAPI BuildSpcrTableEx(IN CONST ACPI_TABLE_GENERATOR *This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, OUT UINTN *CONST TableCount)
STATIC EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr
Definition: SpcrGenerator.c:63
EFI_STATUS EFIAPI AcpiSpcrLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define NAME_STR_SPCR_PORT
Definition: SpcrGenerator.c:48
#define UID_SPCR_PORT
Definition: SpcrGenerator.c:52
STATIC CONST ACPI_TABLE_GENERATOR SpcrGenerator
#define SPCR_FLOW_CONTROL_NONE
Definition: SpcrGenerator.c:56
EFI_STATUS EFIAPI AcpiSpcrLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI ValidateSerialPortInfo(IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfoTable, IN UINT32 SerialPortCount)
EFI_STATUS EFIAPI FreeSsdtSerialPortTable(IN EFI_ACPI_DESCRIPTION_HEADER *Table)
EFI_STATUS EFIAPI BuildSsdtSerialPortTable(IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *AcpiTableInfo, IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo, IN CONST CHAR8 *Name, IN CONST UINT64 Uid, OUT EFI_ACPI_DESCRIPTION_HEADER **Table)
#define CM_NULL_TOKEN
EFI_STATUS EFIAPI AddAcpiHeader(IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST ACPI_TABLE_GENERATOR *CONST Generator, IN OUT EFI_ACPI_DESCRIPTION_HEADER *CONST AcpiHeader, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST UINT32 Length)
Definition: TableHelper.c:114
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
UINT16 PortSubtype
Serial Port subtype.
UINT64 BaseAddress
The physical base address for the serial port.
UINT64 BaudRate
The serial port baud rate.