]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/NonDiscoverableDeviceRegistrationLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / NonDiscoverableDeviceRegistrationLib / NonDiscoverableDeviceRegistrationLib.c
1 /** @file
2 Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
3
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include <PiDxe.h>
9
10 #include <Guid/NonDiscoverableDevice.h>
11
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/DevicePathLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/NonDiscoverableDeviceRegistrationLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18
19 #include <Protocol/DevicePath.h>
20 #include <Protocol/NonDiscoverableDevice.h>
21
22 /**
23 Get Guid form the type of non-discoverable device.
24
25 @param[in] Type The type of non-discoverable device.
26
27 @retval Return the Guid.
28
29 **/
30 STATIC
31 CONST EFI_GUID *
32 GetGuidFromType (
33 IN NON_DISCOVERABLE_DEVICE_TYPE Type
34 )
35 {
36 switch (Type) {
37 case NonDiscoverableDeviceTypeAhci:
38 return &gEdkiiNonDiscoverableAhciDeviceGuid;
39
40 case NonDiscoverableDeviceTypeAmba:
41 return &gEdkiiNonDiscoverableAmbaDeviceGuid;
42
43 case NonDiscoverableDeviceTypeEhci:
44 return &gEdkiiNonDiscoverableEhciDeviceGuid;
45
46 case NonDiscoverableDeviceTypeNvme:
47 return &gEdkiiNonDiscoverableNvmeDeviceGuid;
48
49 case NonDiscoverableDeviceTypeOhci:
50 return &gEdkiiNonDiscoverableOhciDeviceGuid;
51
52 case NonDiscoverableDeviceTypeSdhci:
53 return &gEdkiiNonDiscoverableSdhciDeviceGuid;
54
55 case NonDiscoverableDeviceTypeUfs:
56 return &gEdkiiNonDiscoverableUfsDeviceGuid;
57
58 case NonDiscoverableDeviceTypeUhci:
59 return &gEdkiiNonDiscoverableUhciDeviceGuid;
60
61 case NonDiscoverableDeviceTypeXhci:
62 return &gEdkiiNonDiscoverableXhciDeviceGuid;
63
64 default:
65 return NULL;
66 }
67 }
68
69 #pragma pack (1)
70 typedef struct {
71 VENDOR_DEVICE_PATH Vendor;
72 UINT64 BaseAddress;
73 UINT8 ResourceType;
74 EFI_DEVICE_PATH_PROTOCOL End;
75 } NON_DISCOVERABLE_DEVICE_PATH;
76 #pragma pack ()
77
78 /**
79 Register a non-discoverable MMIO device.
80
81 @param[in] Type The type of non-discoverable device
82 @param[in] DmaType Whether the device is DMA coherent
83 @param[in] InitFunc Initialization routine to be invoked when
84 the device is enabled
85 @param[in,out] Handle The handle onto which to install the
86 non-discoverable device protocol.
87 If Handle is NULL or *Handle is NULL, a
88 new handle will be allocated.
89 @param[in] NumMmioResources The number of UINTN base/size pairs that
90 follow, each describing an MMIO region
91 owned by the device
92 @param[in] ... The variable argument list which contains the
93 info about MmioResources.
94
95 @retval EFI_SUCCESS The registration succeeded.
96 @retval EFI_INVALID_PARAMETER An invalid argument was given
97 @retval Other The registration failed.
98
99 **/
100 EFI_STATUS
101 EFIAPI
102 RegisterNonDiscoverableMmioDevice (
103 IN NON_DISCOVERABLE_DEVICE_TYPE Type,
104 IN NON_DISCOVERABLE_DEVICE_DMA_TYPE DmaType,
105 IN NON_DISCOVERABLE_DEVICE_INIT InitFunc,
106 IN OUT EFI_HANDLE *Handle OPTIONAL,
107 IN UINTN NumMmioResources,
108 ...
109 )
110 {
111 NON_DISCOVERABLE_DEVICE *Device;
112 NON_DISCOVERABLE_DEVICE_PATH *DevicePath;
113 EFI_HANDLE LocalHandle;
114 EFI_STATUS Status;
115 UINTN AllocSize;
116 UINTN Index;
117 VA_LIST Args;
118 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
119 EFI_ACPI_END_TAG_DESCRIPTOR *End;
120 UINTN Base, Size;
121
122 if (Type >= NonDiscoverableDeviceTypeMax ||
123 DmaType >= NonDiscoverableDeviceDmaTypeMax ||
124 NumMmioResources == 0) {
125 return EFI_INVALID_PARAMETER;
126 }
127
128 if (Handle == NULL) {
129 Handle = &LocalHandle;
130 LocalHandle = NULL;
131 }
132
133 AllocSize = sizeof *Device +
134 NumMmioResources * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
135 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR);
136 Device = (NON_DISCOVERABLE_DEVICE *)AllocateZeroPool (AllocSize);
137 if (Device == NULL) {
138 return EFI_OUT_OF_RESOURCES;
139 }
140
141 Device->Type = GetGuidFromType (Type);
142 ASSERT (Device->Type != NULL);
143
144 Device->DmaType = DmaType;
145 Device->Initialize = InitFunc;
146 Device->Resources = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(Device + 1);
147
148 VA_START (Args, NumMmioResources);
149 for (Index = 0; Index < NumMmioResources; Index++) {
150 Desc = &Device->Resources [Index];
151 Base = VA_ARG (Args, UINTN);
152 Size = VA_ARG (Args, UINTN);
153
154 Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
155 Desc->Len = sizeof *Desc - 3;
156 Desc->AddrRangeMin = Base;
157 Desc->AddrLen = Size;
158 Desc->AddrRangeMax = Base + Size - 1;
159 Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
160 Desc->AddrSpaceGranularity = ((EFI_PHYSICAL_ADDRESS)Base + Size > SIZE_4GB) ? 64 : 32;
161 Desc->AddrTranslationOffset = 0;
162 }
163 VA_END (Args);
164
165 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)&Device->Resources [NumMmioResources];
166
167 End->Desc = ACPI_END_TAG_DESCRIPTOR;
168 End->Checksum = 0;
169
170 DevicePath = (NON_DISCOVERABLE_DEVICE_PATH *)CreateDeviceNode (
171 HARDWARE_DEVICE_PATH,
172 HW_VENDOR_DP,
173 sizeof (*DevicePath));
174 if (DevicePath == NULL) {
175 Status = EFI_OUT_OF_RESOURCES;
176 goto FreeDevice;
177 }
178
179 CopyGuid (&DevicePath->Vendor.Guid, &gEdkiiNonDiscoverableDeviceProtocolGuid);
180
181 //
182 // Use the base address and type of the first region to
183 // make the device path unique
184 //
185 DevicePath->BaseAddress = Device->Resources [0].AddrRangeMin;
186 DevicePath->ResourceType = Device->Resources [0].ResType;
187
188 SetDevicePathNodeLength (&DevicePath->Vendor,
189 sizeof (*DevicePath) - sizeof (DevicePath->End));
190 SetDevicePathEndNode (&DevicePath->End);
191
192 Status = gBS->InstallMultipleProtocolInterfaces (Handle,
193 &gEdkiiNonDiscoverableDeviceProtocolGuid, Device,
194 &gEfiDevicePathProtocolGuid, DevicePath,
195 NULL);
196 if (EFI_ERROR (Status)) {
197 goto FreeDevicePath;
198 }
199 return EFI_SUCCESS;
200
201 FreeDevicePath:
202 FreePool (DevicePath);
203
204 FreeDevice:
205 FreePool (Device);
206
207 return Status;
208 }