]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenPvBlkDxe/BlockIo.c
OvmfPkg/Xen: Fix various typos
[mirror_edk2.git] / OvmfPkg / XenPvBlkDxe / BlockIo.c
CommitLineData
5de8a35c
AP
1/** @file\r
2 BlockIo implementation for Xen PV Block driver.\r
3\r
4 This file is implementing the interface between the actual driver in\r
5 BlockFront.c to the BlockIo protocol.\r
6\r
7 Copyright (C) 2014, Citrix Ltd.\r
8\r
b26f0cf9 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
5de8a35c
AP
10\r
11**/\r
12\r
13#include "XenPvBlkDxe.h"\r
14\r
15#include "BlockFront.h"\r
16\r
17///\r
18/// Block I/O Media structure\r
19///\r
20GLOBAL_REMOVE_IF_UNREFERENCED\r
21EFI_BLOCK_IO_MEDIA gXenPvBlkDxeBlockIoMedia = {\r
22 0, // MediaId\r
23 FALSE, // RemovableMedia\r
24 FALSE, // MediaPresent\r
25 FALSE, // LogicalPartition\r
26 TRUE, // ReadOnly\r
27 FALSE, // WriteCaching\r
28 512, // BlockSize\r
29 512, // IoAlign, BlockFront does not support less than 512 bits-aligned.\r
30 0, // LastBlock\r
31 0, // LowestAlignedLba\r
32 0, // LogicalBlocksPerPhysicalBlock\r
33 0 // OptimalTransferLengthGranularity\r
34};\r
35\r
36///\r
37/// Block I/O Protocol instance\r
38///\r
39GLOBAL_REMOVE_IF_UNREFERENCED\r
40EFI_BLOCK_IO_PROTOCOL gXenPvBlkDxeBlockIo = {\r
41 EFI_BLOCK_IO_PROTOCOL_REVISION3, // Revision\r
42 &gXenPvBlkDxeBlockIoMedia, // Media\r
43 XenPvBlkDxeBlockIoReset, // Reset\r
44 XenPvBlkDxeBlockIoReadBlocks, // ReadBlocks\r
45 XenPvBlkDxeBlockIoWriteBlocks, // WriteBlocks\r
46 XenPvBlkDxeBlockIoFlushBlocks // FlushBlocks\r
47};\r
48\r
49\r
50\r
51\r
52/**\r
53 Read/Write BufferSize bytes from Lba into Buffer.\r
54\r
493dde94 55 This function is common to XenPvBlkDxeBlockIoReadBlocks and\r
5de8a35c
AP
56 XenPvBlkDxeBlockIoWriteBlocks.\r
57\r
58 @param This Indicates a pointer to the calling context.\r
59 @param MediaId Id of the media, changes every time the media is replaced.\r
60 @param Lba The starting Logical Block Address to read from/write to.\r
61 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
62 @param Buffer A pointer to the destination/source buffer for the data.\r
63 @param IsWrite Indicate if the operation is write or read.\r
64\r
65 @return See description of XenPvBlkDxeBlockIoReadBlocks and\r
66 XenPvBlkDxeBlockIoWriteBlocks.\r
67**/\r
68STATIC\r
69EFI_STATUS\r
70XenPvBlkDxeBlockIoReadWriteBlocks (\r
71 IN EFI_BLOCK_IO_PROTOCOL *This,\r
72 IN UINT32 MediaId,\r
73 IN EFI_LBA Lba,\r
74 IN UINTN BufferSize,\r
75 IN OUT VOID *Buffer,\r
76 IN BOOLEAN IsWrite\r
77 )\r
78{\r
79 XEN_BLOCK_FRONT_IO IoData;\r
80 EFI_BLOCK_IO_MEDIA *Media = This->Media;\r
81 UINTN Sector;\r
82 EFI_STATUS Status;\r
83\r
84 if (Buffer == NULL) {\r
85 return EFI_INVALID_PARAMETER;\r
86 }\r
87 if (BufferSize == 0) {\r
88 return EFI_SUCCESS;\r
89 }\r
90\r
91 if (BufferSize % Media->BlockSize != 0) {\r
6394c35a
LE
92 DEBUG ((EFI_D_ERROR, "XenPvBlkDxe: Bad buffer size: 0x%Lx\n",\r
93 (UINT64)BufferSize));\r
5de8a35c
AP
94 return EFI_BAD_BUFFER_SIZE;\r
95 }\r
96\r
97 if (Lba > Media->LastBlock ||\r
98 (BufferSize / Media->BlockSize) - 1 > Media->LastBlock - Lba) {\r
6394c35a
LE
99 DEBUG ((EFI_D_ERROR,\r
100 "XenPvBlkDxe: %a with invalid LBA: 0x%Lx, size: 0x%Lx\n",\r
101 IsWrite ? "Write" : "Read", Lba, (UINT64)BufferSize));\r
5de8a35c
AP
102 return EFI_INVALID_PARAMETER;\r
103 }\r
104\r
105 if (IsWrite && Media->ReadOnly) {\r
106 return EFI_WRITE_PROTECTED;\r
107 }\r
108\r
109 if ((Media->IoAlign > 1) && (UINTN)Buffer & (Media->IoAlign - 1)) {\r
110 //\r
111 // Grub2 does not appear to respect IoAlign of 512, so reallocate the\r
112 // buffer here.\r
113 //\r
114 VOID *NewBuffer;\r
115\r
116 //\r
117 // Try again with a properly aligned buffer.\r
118 //\r
119 NewBuffer = AllocateAlignedPages((BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE,\r
120 Media->IoAlign);\r
121 if (!IsWrite) {\r
122 Status = XenPvBlkDxeBlockIoReadBlocks (This, MediaId,\r
123 Lba, BufferSize, NewBuffer);\r
124 CopyMem (Buffer, NewBuffer, BufferSize);\r
125 } else {\r
126 CopyMem (NewBuffer, Buffer, BufferSize);\r
127 Status = XenPvBlkDxeBlockIoWriteBlocks (This, MediaId,\r
128 Lba, BufferSize, NewBuffer);\r
129 }\r
130 FreeAlignedPages (NewBuffer, (BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE);\r
131 return Status;\r
132 }\r
133\r
134 IoData.Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (This);\r
860088f2 135 Sector = (UINTN)MultU64x32 (Lba, Media->BlockSize / 512);\r
5de8a35c
AP
136\r
137 while (BufferSize > 0) {\r
138 if (((UINTN)Buffer & EFI_PAGE_MASK) == 0) {\r
139 IoData.Size = MIN (BLKIF_MAX_SEGMENTS_PER_REQUEST * EFI_PAGE_SIZE,\r
140 BufferSize);\r
141 } else {\r
142 IoData.Size = MIN ((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) * EFI_PAGE_SIZE,\r
143 BufferSize);\r
144 }\r
145\r
146 IoData.Buffer = Buffer;\r
147 IoData.Sector = Sector;\r
148 BufferSize -= IoData.Size;\r
149 Buffer = (VOID*) ((UINTN) Buffer + IoData.Size);\r
150 Sector += IoData.Size / 512;\r
151 Status = XenPvBlockIo (&IoData, IsWrite);\r
152 if (EFI_ERROR (Status)) {\r
8c0b0b34 153 DEBUG ((EFI_D_ERROR, "XenPvBlkDxe: Error during %a operation.\n",\r
5de8a35c
AP
154 IsWrite ? "write" : "read"));\r
155 return Status;\r
156 }\r
157 }\r
158 return EFI_SUCCESS;\r
159}\r
160\r
161\r
162/**\r
163 Read BufferSize bytes from Lba into Buffer.\r
164\r
165 @param This Indicates a pointer to the calling context.\r
166 @param MediaId Id of the media, changes every time the media is replaced.\r
167 @param Lba The starting Logical Block Address to read from\r
168 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
169 @param Buffer A pointer to the destination buffer for the data. The caller is\r
170 responsible for either having implicit or explicit ownership of the buffer.\r
171\r
172 @retval EFI_SUCCESS The data was read correctly from the device.\r
173 @retval EFI_DEVICE_ERROR The device reported an error while performing the read.\r
174 @retval EFI_NO_MEDIA There is no media in the device.\r
493dde94 175 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
5de8a35c
AP
176 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
177 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,\r
178 or the buffer is not on proper alignment.\r
179\r
180**/\r
181EFI_STATUS\r
182EFIAPI\r
183XenPvBlkDxeBlockIoReadBlocks (\r
184 IN EFI_BLOCK_IO_PROTOCOL *This,\r
185 IN UINT32 MediaId,\r
186 IN EFI_LBA Lba,\r
187 IN UINTN BufferSize,\r
188 OUT VOID *Buffer\r
189 )\r
190{\r
191 return XenPvBlkDxeBlockIoReadWriteBlocks (This,\r
192 MediaId, Lba, BufferSize, Buffer, FALSE);\r
193}\r
194\r
195/**\r
196 Write BufferSize bytes from Lba into Buffer.\r
197\r
198 @param This Indicates a pointer to the calling context.\r
199 @param MediaId The media ID that the write request is for.\r
200 @param Lba The starting logical block address to be written. The caller is\r
201 responsible for writing to only legitimate locations.\r
202 @param BufferSize Size of Buffer, must be a multiple of device block size.\r
203 @param Buffer A pointer to the source buffer for the data.\r
204\r
205 @retval EFI_SUCCESS The data was written correctly to the device.\r
206 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
207 @retval EFI_DEVICE_ERROR The device reported an error while performing the write.\r
208 @retval EFI_NO_MEDIA There is no media in the device.\r
493dde94 209 @retval EFI_MEDIA_CHANGED The MediaId does not match the current device.\r
5de8a35c
AP
210 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.\r
211 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,\r
212 or the buffer is not on proper alignment.\r
213\r
214**/\r
215EFI_STATUS\r
216EFIAPI\r
217XenPvBlkDxeBlockIoWriteBlocks (\r
218 IN EFI_BLOCK_IO_PROTOCOL *This,\r
219 IN UINT32 MediaId,\r
220 IN EFI_LBA Lba,\r
221 IN UINTN BufferSize,\r
222 IN VOID *Buffer\r
223 )\r
224{\r
225 return XenPvBlkDxeBlockIoReadWriteBlocks (This,\r
226 MediaId, Lba, BufferSize, Buffer, TRUE);\r
227}\r
228\r
229/**\r
230 Flush the Block Device.\r
231\r
232 @param This Indicates a pointer to the calling context.\r
233\r
234 @retval EFI_SUCCESS All outstanding data was written to the device\r
493dde94 235 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data\r
5de8a35c
AP
236 @retval EFI_NO_MEDIA There is no media in the device.\r
237\r
238**/\r
239EFI_STATUS\r
240EFIAPI\r
241XenPvBlkDxeBlockIoFlushBlocks (\r
242 IN EFI_BLOCK_IO_PROTOCOL *This\r
243 )\r
244{\r
245 XenPvBlockSync (XEN_BLOCK_FRONT_FROM_BLOCK_IO (This));\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249/**\r
250 Reset the block device hardware.\r
251\r
252 @param[in] This Indicates a pointer to the calling context.\r
253 @param[in] ExtendedVerification Not used.\r
254\r
255 @retval EFI_SUCCESS The device was reset.\r
256\r
257**/\r
258EFI_STATUS\r
259EFIAPI\r
260XenPvBlkDxeBlockIoReset (\r
261 IN EFI_BLOCK_IO_PROTOCOL *This,\r
262 IN BOOLEAN ExtendedVerification\r
263 )\r
264{\r
265 //\r
266 // Since the initialization of the devices is done, then the device is\r
267 // working correctly.\r
268 //\r
269 return EFI_SUCCESS;\r
270}\r