]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChainProtocol.c
1.1.07 release
[Ventoy.git] / EDK2 / edk2_mod / edk2-edk2-stable201911 / MdeModulePkg / Application / VDiskChain / VDiskChainProtocol.c
1 /******************************************************************************
2 * VDiskChainProtocol.c
3 *
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <Uefi.h>
22 #include <Library/DebugLib.h>
23 #include <Library/PrintLib.h>
24 #include <Library/UefiLib.h>
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/DevicePathLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/UefiRuntimeServicesTableLib.h>
30 #include <Library/UefiApplicationEntryPoint.h>
31 #include <Protocol/LoadedImage.h>
32 #include <Guid/FileInfo.h>
33 #include <Guid/FileSystemInfo.h>
34 #include <Protocol/BlockIo.h>
35 #include <Protocol/RamDisk.h>
36 #include <Protocol/SimpleFileSystem.h>
37 #include <VDiskChain.h>
38
39 /* EFI block device vendor device path GUID */
40 EFI_GUID gVDiskBlockDevicePathGuid = VDISK_BLOCK_DEVICE_PATH_GUID;
41
42 EFI_STATUS EFIAPI vdisk_block_io_reset
43 (
44 IN EFI_BLOCK_IO_PROTOCOL *This,
45 IN BOOLEAN ExtendedVerification
46 )
47 {
48 (VOID)This;
49 (VOID)ExtendedVerification;
50 return EFI_SUCCESS;
51 }
52
53 EFI_STATUS EFIAPI vdisk_block_io_flush(IN EFI_BLOCK_IO_PROTOCOL *This)
54 {
55 (VOID)This;
56 return EFI_SUCCESS;
57 }
58
59 EFI_STATUS EFIAPI vdisk_block_io_read
60 (
61 IN EFI_BLOCK_IO_PROTOCOL *This,
62 IN UINT32 MediaId,
63 IN EFI_LBA Lba,
64 IN UINTN BufferSize,
65 OUT VOID *Buffer
66 )
67 {
68 (VOID)This;
69 (VOID)MediaId;
70
71 debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
72 CopyMem(Buffer, g_disk_buf_addr + (Lba * 512), BufferSize);
73
74 return EFI_SUCCESS;
75 }
76
77 EFI_STATUS EFIAPI vdisk_block_io_write
78 (
79 IN EFI_BLOCK_IO_PROTOCOL *This,
80 IN UINT32 MediaId,
81 IN EFI_LBA Lba,
82 IN UINTN BufferSize,
83 IN VOID *Buffer
84 )
85 {
86 (VOID)This;
87 (VOID)MediaId;
88 (VOID)Buffer;
89
90 debug("vdisk_block_io_read %lu %lu\n", Lba, BufferSize / 512);
91 return EFI_WRITE_PROTECTED;
92 }
93
94 EFI_STATUS EFIAPI vdisk_fill_device_path(VOID)
95 {
96 UINTN NameLen = 0;
97 UINT8 TmpBuf[128] = {0};
98 VENDOR_DEVICE_PATH *venPath = NULL;
99
100 venPath = (VENDOR_DEVICE_PATH *)TmpBuf;
101 NameLen = StrSize(VDISK_BLOCK_DEVICE_PATH_NAME);
102 venPath->Header.Type = HARDWARE_DEVICE_PATH;
103 venPath->Header.SubType = HW_VENDOR_DP;
104 venPath->Header.Length[0] = sizeof(VENDOR_DEVICE_PATH) + NameLen;
105 venPath->Header.Length[1] = 0;
106 CopyMem(&venPath->Guid, &gVDiskBlockDevicePathGuid, sizeof(EFI_GUID));
107 CopyMem(venPath + 1, VDISK_BLOCK_DEVICE_PATH_NAME, NameLen);
108
109 gVDiskBlockData.Path = AppendDevicePathNode(NULL, (EFI_DEVICE_PATH_PROTOCOL *)TmpBuf);
110 gVDiskBlockData.DevicePathCompareLen = sizeof(VENDOR_DEVICE_PATH) + NameLen;
111
112 debug("gVDiskBlockData.Path=<%s>\n", ConvertDevicePathToText(gVDiskBlockData.Path, FALSE, FALSE));
113
114 return EFI_SUCCESS;
115 }
116
117 EFI_STATUS EFIAPI vdisk_connect_driver(IN EFI_HANDLE ControllerHandle, IN CONST CHAR16 *DrvName)
118 {
119 UINTN i = 0;
120 UINTN Count = 0;
121 CHAR16 *DriverName = NULL;
122 EFI_HANDLE *Handles = NULL;
123 EFI_HANDLE DrvHandles[2] = { NULL };
124 EFI_STATUS Status = EFI_SUCCESS;
125 EFI_COMPONENT_NAME_PROTOCOL *NameProtocol = NULL;
126 EFI_COMPONENT_NAME2_PROTOCOL *Name2Protocol = NULL;
127
128 debug("vdisk_connect_driver <%s>...", DrvName);
129
130 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentName2ProtocolGuid,
131 NULL, &Count, &Handles);
132 if (EFI_ERROR(Status))
133 {
134 return Status;
135 }
136
137 for (i = 0; i < Count; i++)
138 {
139 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentName2ProtocolGuid, (VOID **)&Name2Protocol);
140 if (EFI_ERROR(Status))
141 {
142 continue;
143 }
144
145 Status = Name2Protocol->GetDriverName(Name2Protocol, "en", &DriverName);
146 if (EFI_ERROR(Status) || NULL == DriverName)
147 {
148 continue;
149 }
150
151 if (StrStr(DriverName, DrvName))
152 {
153 debug("Find driver name2:<%s>: <%s>", DriverName, DrvName);
154 DrvHandles[0] = Handles[i];
155 break;
156 }
157 }
158
159 if (i < Count)
160 {
161 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
162 debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
163 goto end;
164 }
165
166 debug("%s NOT found, now try COMPONENT_NAME", DrvName);
167
168 Count = 0;
169 FreePool(Handles);
170 Handles = NULL;
171
172 Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid,
173 NULL, &Count, &Handles);
174 if (EFI_ERROR(Status))
175 {
176 return Status;
177 }
178
179 for (i = 0; i < Count; i++)
180 {
181 Status = gBS->HandleProtocol(Handles[i], &gEfiComponentNameProtocolGuid, (VOID **)&NameProtocol);
182 if (EFI_ERROR(Status))
183 {
184 continue;
185 }
186
187 Status = NameProtocol->GetDriverName(NameProtocol, "en", &DriverName);
188 if (EFI_ERROR(Status))
189 {
190 continue;
191 }
192
193 if (StrStr(DriverName, DrvName))
194 {
195 debug("Find driver name:<%s>: <%s>", DriverName, DrvName);
196 DrvHandles[0] = Handles[i];
197 break;
198 }
199 }
200
201 if (i < Count)
202 {
203 Status = gBS->ConnectController(ControllerHandle, DrvHandles, NULL, TRUE);
204 debug("vdisk_connect_driver:<%s> <%r>", DrvName, Status);
205 goto end;
206 }
207
208 Status = EFI_NOT_FOUND;
209
210 end:
211 FreePool(Handles);
212
213 return Status;
214 }
215
216 EFI_STATUS EFIAPI vdisk_install_blockio(IN EFI_HANDLE ImageHandle, IN UINT64 ImgSize)
217 {
218 EFI_STATUS Status = EFI_SUCCESS;
219 EFI_BLOCK_IO_PROTOCOL *pBlockIo = &(gVDiskBlockData.BlockIo);
220
221 vdisk_fill_device_path();
222
223 debug("install block io protocol %p", ImageHandle);
224 vdisk_debug_pause();
225
226 gVDiskBlockData.Media.BlockSize = 512;
227 gVDiskBlockData.Media.LastBlock = ImgSize / 512 - 1;
228 gVDiskBlockData.Media.ReadOnly = TRUE;
229 gVDiskBlockData.Media.MediaPresent = 1;
230 gVDiskBlockData.Media.LogicalBlocksPerPhysicalBlock = 1;
231
232 pBlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
233 pBlockIo->Media = &(gVDiskBlockData.Media);
234 pBlockIo->Reset = vdisk_block_io_reset;
235 pBlockIo->ReadBlocks = vdisk_block_io_read;
236 pBlockIo->WriteBlocks = vdisk_block_io_write;
237 pBlockIo->FlushBlocks = vdisk_block_io_flush;
238
239 Status = gBS->InstallMultipleProtocolInterfaces(&gVDiskBlockData.Handle,
240 &gEfiBlockIoProtocolGuid, &gVDiskBlockData.BlockIo,
241 &gEfiDevicePathProtocolGuid, gVDiskBlockData.Path,
242 NULL);
243 debug("Install protocol %r %p", Status, gVDiskBlockData.Handle);
244 if (EFI_ERROR(Status))
245 {
246 return Status;
247 }
248
249 Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Disk I/O Driver");
250 debug("Connect disk IO driver %r", Status);
251
252 Status = vdisk_connect_driver(gVDiskBlockData.Handle, L"Partition Driver");
253 debug("Connect partition driver %r", Status);
254 if (EFI_ERROR(Status))
255 {
256 Status = gBS->ConnectController(gVDiskBlockData.Handle, NULL, NULL, TRUE);
257 debug("Connect all controller %r", Status);
258 }
259
260 vdisk_debug_pause();
261
262 return EFI_SUCCESS;
263 }
264