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