/** @file Flattened Device Tree parser library for KvmTool. Copyright (c) 2021, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "FdtHwInfoParser.h" #include "BootArch/ArmBootArchParser.h" #include "GenericTimer/ArmGenericTimerParser.h" #include "Gic/ArmGicDispatcher.h" #include "Pci/ArmPciConfigSpaceParser.h" #include "Serial/ArmSerialPortParser.h" /** Ordered table of parsers/dispatchers. A parser parses a Device Tree to populate a specific CmObj type. None, one or many CmObj can be created by the parser. The created CmObj are then handed to the parser's caller through the HW_INFO_ADD_OBJECT interface. This can also be a dispatcher. I.e. a function that not parsing a Device Tree but calling other parsers. */ STATIC CONST FDT_HW_INFO_PARSER_FUNC HwInfoParserTable[] = { ArmBootArchInfoParser, ArmGenericTimerInfoParser, ArmGicDispatcher, ArmPciConfigInfoParser, SerialPortDispatcher }; /** Main dispatcher: sequentially call the parsers/dispatchers of the HwInfoParserTable. A parser parses a Device Tree to populate a specific CmObj type. None, one or many CmObj can be created by the parser. The created CmObj are then handed to the parser's caller through the HW_INFO_ADD_OBJECT interface. This can also be a dispatcher. I.e. a function that not parsing a Device Tree but calling other parsers. @param [in] FdtParserHandle A handle to the parser instance. @param [in] FdtBranch When searching for DT node name, restrict the search to this Device Tree branch. @retval EFI_SUCCESS The function completed successfully. @retval EFI_ABORTED An error occurred. @retval EFI_INVALID_PARAMETER Invalid parameter. @retval EFI_NOT_FOUND Not found. @retval EFI_UNSUPPORTED Unsupported. **/ STATIC EFI_STATUS EFIAPI MainDispatcher ( IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle, IN INT32 FdtBranch ) { EFI_STATUS Status; UINT32 Index; if (fdt_check_header (FdtParserHandle->Fdt) < 0) { ASSERT (0); return EFI_INVALID_PARAMETER; } for (Index = 0; Index < ARRAY_SIZE (HwInfoParserTable); Index++) { Status = HwInfoParserTable[Index]( FdtParserHandle, FdtBranch ); if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { // If EFI_NOT_FOUND, the parser didn't find information in the DT. // Don't trigger an error. ASSERT (0); return Status; } } // for return EFI_SUCCESS; } /** Initialise the HwInfoParser. The HwInfoParser shall use the information provided by the HwDataSource to initialise the internal state of the parser or to index the data. This internal state shall be linked to the ParserHandle using an implementation defined mechanism. @param [in] HwDataSource Pointer to the blob containing the hardware information. It can be a pointer to a Device Tree, an XML file, etc. or any other data structure defined by the HwInfoParser. @param [in] Context A pointer to the caller's context. @param [in] HwInfoAdd Function pointer called by the parser when adding information. @param [out] ParserHandle A handle to the parser instance. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Invalid parameter. **/ EFI_STATUS EFIAPI HwInfoParserInit ( IN VOID *HwDataSource, IN VOID *Context, IN HW_INFO_ADD_OBJECT HwInfoAdd, OUT HW_INFO_PARSER_HANDLE *ParserHandle ) { FDT_HW_INFO_PARSER *FdtParserHandle; if ((ParserHandle == NULL) || (HwInfoAdd == NULL) || (HwDataSource == NULL) || (fdt_check_header (HwDataSource) < 0)) { ASSERT (0); return EFI_INVALID_PARAMETER; } FdtParserHandle = AllocateZeroPool (sizeof (FDT_HW_INFO_PARSER)); if (FdtParserHandle == NULL) { *ParserHandle = NULL; return EFI_OUT_OF_RESOURCES; } // The HwDataSource is a pointer to the FDT data. FdtParserHandle->Fdt = HwDataSource; FdtParserHandle->Context = Context; FdtParserHandle->HwInfoAdd = HwInfoAdd; *ParserHandle = (HW_INFO_PARSER_HANDLE)FdtParserHandle; return EFI_SUCCESS; } /** Parse the data provided by the HwDataSource. @param [in] ParserHandle A handle to the parser instance. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Invalid parameter. @retval EFI_OUT_OF_RESOURCES An allocation has failed. **/ EFI_STATUS EFIAPI HwInfoParse ( IN HW_INFO_PARSER_HANDLE ParserHandle ) { EFI_STATUS Status; if (ParserHandle == NULL) { ASSERT (0); return EFI_INVALID_PARAMETER; } // Call all the parsers from the root node (-1). Status = MainDispatcher ( (FDT_HW_INFO_PARSER_HANDLE)ParserHandle, -1 ); ASSERT_EFI_ERROR (Status); return Status; } /** Cleanup any internal state and resources that were allocated by the HwInfoParser. @param [in] ParserHandle A handle to the parser instance. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Invalid parameter. **/ EFI_STATUS EFIAPI HwInfoParserShutdown ( IN HW_INFO_PARSER_HANDLE ParserHandle ) { if (ParserHandle == NULL) { ASSERT (0); return EFI_INVALID_PARAMETER; } FreePool (ParserHandle); return EFI_SUCCESS; }