1 /** @file
2 *  Manage XenBus device path and I/O handles
3 *
4 *  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
5 *
6 *  This program and the accompanying materials are
7 *  licensed and made available under the terms and conditions of the BSD License
8 *  which accompanies this distribution.  The full text of the license may be found at
9 *  http://opensource.org/licenses/bsd-license.php
10 *
11 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15 
16 #include <Library/BaseLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/UefiLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/DevicePathLib.h>
23 #include <Library/XenIoMmioLib.h>
24 
25 #include <Protocol/XenIo.h>
26 #include <Guid/XenBusRootDevice.h>
27 
28 #pragma pack (1)
29 typedef struct {
30   VENDOR_DEVICE_PATH                  Vendor;
31   EFI_PHYSICAL_ADDRESS                GrantTableAddress;
32   EFI_DEVICE_PATH_PROTOCOL            End;
33 } XENBUS_ROOT_DEVICE_PATH;
34 #pragma pack ()
35 
36 STATIC CONST XENBUS_ROOT_DEVICE_PATH mXenBusRootDevicePathTemplate = {
37   {
38     {
39       HARDWARE_DEVICE_PATH,
40       HW_VENDOR_DP,
41       { sizeof (VENDOR_DEVICE_PATH) + sizeof (EFI_PHYSICAL_ADDRESS), 0 }
42     },
43     XENBUS_ROOT_DEVICE_GUID,
44   },
45   0,
46   {
47     END_DEVICE_PATH_TYPE,
48     END_ENTIRE_DEVICE_PATH_SUBTYPE,
49     { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
50   }
51 };
52 
53 /**
54 
55   Install the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols on
56   the handle pointed to by @Handle, or on a new handle if it points to
57   NULL
58 
59   @param  Handle                Pointer to the handle to install the protocols
60                                 on, may point to a NULL handle.
61 
62   @param  GrantTableAddress     The address of the Xen grant table
63 
64   @retval EFI_SUCCESS           Protocols were installed successfully
65 
66   @retval EFI_OUT_OF_RESOURCES  The function failed to allocate memory required
67                                 by the XenIo MMIO and device path protocols
68 
69   @return                       Status code returned by the boot service
70                                 InstallMultipleProtocolInterfaces ()
71 
72 **/
73 EFI_STATUS
XenIoMmioInstall(IN OUT EFI_HANDLE * Handle,IN EFI_PHYSICAL_ADDRESS GrantTableAddress)74 XenIoMmioInstall (
75   IN OUT   EFI_HANDLE              *Handle,
76   IN       EFI_PHYSICAL_ADDRESS    GrantTableAddress
77   )
78 {
79   EFI_STATUS                     Status;
80   XENIO_PROTOCOL                 *XenIo;
81   XENBUS_ROOT_DEVICE_PATH        *XenBusDevicePath;
82   EFI_HANDLE                     OutHandle;
83 
84   ASSERT (Handle != NULL);
85 
86   OutHandle = *Handle;
87 
88   XenIo = AllocateZeroPool (sizeof *XenIo);
89   if (!XenIo) {
90     return EFI_OUT_OF_RESOURCES;
91   }
92   XenIo->GrantTableAddress = GrantTableAddress;
93 
94   XenBusDevicePath = AllocateCopyPool (sizeof *XenBusDevicePath,
95                        &mXenBusRootDevicePathTemplate);
96   if (!XenBusDevicePath) {
97     DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
98     Status = EFI_OUT_OF_RESOURCES;
99     goto FreeXenIo;
100   }
101   XenBusDevicePath->GrantTableAddress = GrantTableAddress;
102 
103   Status = gBS->InstallMultipleProtocolInterfaces (&OutHandle,
104                   &gEfiDevicePathProtocolGuid, XenBusDevicePath,
105                   &gXenIoProtocolGuid, XenIo,
106                   NULL);
107   if (!EFI_ERROR (Status)) {
108     *Handle = OutHandle;
109     return EFI_SUCCESS;
110   }
111 
112   DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH and "
113     "XENIO_PROTOCOL protocols on handle %p (Status == %r)\n",
114     __FUNCTION__, OutHandle, Status));
115 
116   FreePool (XenBusDevicePath);
117 
118 FreeXenIo:
119   FreePool (XenIo);
120   return Status;
121 }
122 
123 /**
124 
125   Uninstall the XENBUS_ROOT_DEVICE_PATH and XENIO_PROTOCOL protocols
126 
127   @param  Handle          Handle onto which the protocols have been installed
128                           earlier by XenIoMmioInstall ()
129 
130   @retval EFI_SUCCESS     Protocols were uninstalled successfully
131 
132   @return                 Status code returned by the boot service
133                           UninstallMultipleProtocolInterfaces ()
134 
135 **/
136 EFI_STATUS
XenIoMmioUninstall(IN EFI_HANDLE Handle)137 XenIoMmioUninstall (
138   IN       EFI_HANDLE              Handle
139   )
140 {
141   EFI_STATUS    Status;
142   VOID          *XenIo;
143   VOID          *XenBusDevicePath;
144 
145   XenBusDevicePath = NULL;
146   gBS->OpenProtocol (Handle, &gEfiDevicePathProtocolGuid, &XenBusDevicePath,
147          NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
148 
149   XenIo = NULL;
150   gBS->OpenProtocol (Handle, &gXenIoProtocolGuid, &XenIo,
151          NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
152 
153   Status = gBS->UninstallMultipleProtocolInterfaces (Handle,
154                   &gEfiDevicePathProtocolGuid, XenBusDevicePath,
155                   &gXenIoProtocolGuid, XenIo,
156                   NULL);
157 
158   if (EFI_ERROR (Status)) {
159     return Status;
160   }
161 
162   FreePool (XenBusDevicePath);
163   FreePool (XenIo);
164 
165   return EFI_SUCCESS;
166 }
167