1/** @file
2  Library instance of PciHostBridgeLib library class for coreboot.
3
4  Copyright (C) 2016, Red Hat, Inc.
5  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
6
7  This program and the accompanying materials are licensed and made available
8  under the terms and conditions of the BSD License which accompanies this
9  distribution.  The full text of the license may be found at
10  http://opensource.org/licenses/bsd-license.php.
11
12  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
13  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15**/
16#include <PiDxe.h>
17
18#include <IndustryStandard/Pci.h>
19#include <Protocol/PciHostBridgeResourceAllocation.h>
20#include <Protocol/PciRootBridgeIo.h>
21
22#include <Library/BaseMemoryLib.h>
23#include <Library/DebugLib.h>
24#include <Library/DevicePathLib.h>
25#include <Library/MemoryAllocationLib.h>
26#include <Library/PciHostBridgeLib.h>
27#include <Library/PciLib.h>
28
29#include "PciHostBridge.h"
30
31STATIC
32CONST
33CB_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
34  {
35    {
36      ACPI_DEVICE_PATH,
37      ACPI_DP,
38      {
39        (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
40        (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
41      }
42    },
43    EISA_PNP_ID(0x0A03), // HID
44    0                    // UID
45  },
46
47  {
48    END_DEVICE_PATH_TYPE,
49    END_ENTIRE_DEVICE_PATH_SUBTYPE,
50    {
51      END_DEVICE_PATH_LENGTH,
52      0
53    }
54  }
55};
56
57
58/**
59  Initialize a PCI_ROOT_BRIDGE structure.
60
61  @param[in]  Supports         Supported attributes.
62
63  @param[in]  Attributes       Initial attributes.
64
65  @param[in]  AllocAttributes  Allocation attributes.
66
67  @param[in]  RootBusNumber    The bus number to store in RootBus.
68
69  @param[in]  MaxSubBusNumber  The inclusive maximum bus number that can be
70                               assigned to any subordinate bus found behind any
71                               PCI bridge hanging off this root bus.
72
73                               The caller is repsonsible for ensuring that
74                               RootBusNumber <= MaxSubBusNumber. If
75                               RootBusNumber equals MaxSubBusNumber, then the
76                               root bus has no room for subordinate buses.
77
78  @param[in]  Io               IO aperture.
79
80  @param[in]  Mem              MMIO aperture.
81
82  @param[in]  MemAbove4G       MMIO aperture above 4G.
83
84  @param[in]  PMem             Prefetchable MMIO aperture.
85
86  @param[in]  PMemAbove4G      Prefetchable MMIO aperture above 4G.
87
88  @param[out] RootBus          The PCI_ROOT_BRIDGE structure (allocated by the
89                               caller) that should be filled in by this
90                               function.
91
92  @retval EFI_SUCCESS           Initialization successful. A device path
93                                consisting of an ACPI device path node, with
94                                UID = RootBusNumber, has been allocated and
95                                linked into RootBus.
96
97  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
98**/
99EFI_STATUS
100InitRootBridge (
101  IN  UINT64                   Supports,
102  IN  UINT64                   Attributes,
103  IN  UINT64                   AllocAttributes,
104  IN  UINT8                    RootBusNumber,
105  IN  UINT8                    MaxSubBusNumber,
106  IN  PCI_ROOT_BRIDGE_APERTURE *Io,
107  IN  PCI_ROOT_BRIDGE_APERTURE *Mem,
108  IN  PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
109  IN  PCI_ROOT_BRIDGE_APERTURE *PMem,
110  IN  PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
111  OUT PCI_ROOT_BRIDGE          *RootBus
112)
113{
114  CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
115
116  //
117  // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
118  //
119  ZeroMem (RootBus, sizeof *RootBus);
120
121  RootBus->Segment = 0;
122
123  RootBus->Supports   = Supports;
124  RootBus->Attributes = Attributes;
125
126  RootBus->DmaAbove4G = FALSE;
127
128  RootBus->AllocationAttributes = AllocAttributes;
129  RootBus->Bus.Base  = RootBusNumber;
130  RootBus->Bus.Limit = MaxSubBusNumber;
131  CopyMem (&RootBus->Io, Io, sizeof (*Io));
132  CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
133  CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
134  CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
135  CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
136
137  RootBus->NoExtendedConfigSpace = FALSE;
138
139  DevicePath = AllocateCopyPool (sizeof (mRootBridgeDevicePathTemplate),
140                                 &mRootBridgeDevicePathTemplate);
141  if (DevicePath == NULL) {
142    DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
143    return EFI_OUT_OF_RESOURCES;
144  }
145  DevicePath->AcpiDevicePath.UID = RootBusNumber;
146  RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
147
148  DEBUG ((EFI_D_INFO,
149          "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
150          __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
151  return EFI_SUCCESS;
152}
153
154
155/**
156  Return all the root bridge instances in an array.
157
158  @param Count  Return the count of root bridge instances.
159
160  @return All the root bridge instances in an array.
161          The array should be passed into PciHostBridgeFreeRootBridges()
162          when it's not used.
163**/
164PCI_ROOT_BRIDGE *
165EFIAPI
166PciHostBridgeGetRootBridges (
167  UINTN *Count
168)
169{
170  return ScanForRootBridges (Count);
171}
172
173
174/**
175  Free the root bridge instances array returned from
176  PciHostBridgeGetRootBridges().
177
178  @param  The root bridge instances array.
179  @param  The count of the array.
180**/
181VOID
182EFIAPI
183PciHostBridgeFreeRootBridges (
184  PCI_ROOT_BRIDGE *Bridges,
185  UINTN           Count
186)
187{
188  if (Bridges == NULL && Count == 0) {
189    return;
190  }
191  ASSERT (Bridges != NULL && Count > 0);
192
193  do {
194    --Count;
195    FreePool (Bridges[Count].DevicePath);
196  } while (Count > 0);
197
198  FreePool (Bridges);
199}
200
201
202/**
203  Inform the platform that the resource conflict happens.
204
205  @param HostBridgeHandle Handle of the Host Bridge.
206  @param Configuration    Pointer to PCI I/O and PCI memory resource
207                          descriptors. The Configuration contains the resources
208                          for all the root bridges. The resource for each root
209                          bridge is terminated with END descriptor and an
210                          additional END is appended indicating the end of the
211                          entire resources. The resource descriptor field
212                          values follow the description in
213                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
214                          .SubmitResources().
215**/
216VOID
217EFIAPI
218PciHostBridgeResourceConflict (
219  EFI_HANDLE                        HostBridgeHandle,
220  VOID                              *Configuration
221)
222{
223  //
224  // coreboot UEFI Payload does not do PCI enumeration and should not call this
225  // library interface.
226  //
227  ASSERT (FALSE);
228}
229