]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
MdeModulePkg/RamDiskDxe: Perform MediaId check first in BlkIo services
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / RamDiskDxe / RamDiskBlockIo.c
CommitLineData
20752cb8
HW
1/** @file\r
2 Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.\r
3\r
0feca62c 4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
20752cb8
HW
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "RamDiskImpl.h"\r
16\r
17//\r
18// The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle\r
19// for newly registered RAM disks\r
20//\r
21EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate = {\r
22 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
23 (EFI_BLOCK_IO_MEDIA *) 0,\r
24 RamDiskBlkIoReset,\r
25 RamDiskBlkIoReadBlocks,\r
26 RamDiskBlkIoWriteBlocks,\r
27 RamDiskBlkIoFlushBlocks\r
28};\r
29\r
216fefa3
HW
30//\r
31// The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle\r
32// for newly registered RAM disks\r
33//\r
34EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template = {\r
35 (EFI_BLOCK_IO_MEDIA *) 0,\r
36 RamDiskBlkIo2Reset,\r
37 RamDiskBlkIo2ReadBlocksEx,\r
38 RamDiskBlkIo2WriteBlocksEx,\r
39 RamDiskBlkIo2FlushBlocksEx\r
40};\r
41\r
20752cb8
HW
42\r
43/**\r
216fefa3 44 Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.\r
20752cb8
HW
45\r
46 @param[in] PrivateData Points to RAM disk private data.\r
47\r
48**/\r
49VOID\r
50RamDiskInitBlockIo (\r
51 IN RAM_DISK_PRIVATE_DATA *PrivateData\r
52 )\r
53{\r
54 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
216fefa3 55 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
20752cb8
HW
56 EFI_BLOCK_IO_MEDIA *Media;\r
57\r
216fefa3
HW
58 BlockIo = &PrivateData->BlockIo;\r
59 BlockIo2 = &PrivateData->BlockIo2;\r
60 Media = &PrivateData->Media;\r
20752cb8
HW
61\r
62 CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));\r
216fefa3 63 CopyMem (BlockIo2, &mRamDiskBlockIo2Template, sizeof (EFI_BLOCK_IO2_PROTOCOL));\r
20752cb8
HW
64\r
65 BlockIo->Media = Media;\r
216fefa3 66 BlockIo2->Media = Media;\r
20752cb8
HW
67 Media->RemovableMedia = FALSE;\r
68 Media->MediaPresent = TRUE;\r
69 Media->LogicalPartition = FALSE;\r
70 Media->ReadOnly = FALSE;\r
71 Media->WriteCaching = FALSE;\r
72 Media->BlockSize = RAM_DISK_BLOCK_SIZE;\r
73 Media->LastBlock = DivU64x32 (\r
74 PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1,\r
75 RAM_DISK_BLOCK_SIZE\r
76 ) - 1;\r
77}\r
78\r
79\r
80/**\r
81 Reset the Block Device.\r
82\r
83 @param This Indicates a pointer to the calling context.\r
84 @param ExtendedVerification Driver may perform diagnostics on reset.\r
85\r
86 @retval EFI_SUCCESS The device was reset.\r
87 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
88 not be reset.\r
89\r
90**/\r
91EFI_STATUS\r
92EFIAPI\r
93RamDiskBlkIoReset (\r
94 IN EFI_BLOCK_IO_PROTOCOL *This,\r
95 IN BOOLEAN ExtendedVerification\r
96 )\r
97{\r
98 return EFI_SUCCESS;\r
99}\r
100\r
101\r
102/**\r
103 Read BufferSize bytes from Lba into Buffer.\r
104\r
105 @param[in] This Indicates a pointer to the calling context.\r
106 @param[in] MediaId Id of the media, changes every time the media is\r
107 replaced.\r
108 @param[in] Lba The starting Logical Block Address to read from.\r
109 @param[in] BufferSize Size of Buffer, must be a multiple of device block\r
110 size.\r
111 @param[out] Buffer A pointer to the destination buffer for the data.\r
112 The caller is responsible for either having\r
113 implicit or explicit ownership of the buffer.\r
114\r
115 @retval EFI_SUCCESS The data was read correctly from the device.\r
116 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
117 the read.\r
118 @retval EFI_NO_MEDIA There is no media in the device.\r
119 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current\r
120 device.\r
121 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block\r
122 size of the device.\r
123 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
124 valid, or the buffer is not on proper alignment.\r
125\r
126**/\r
127EFI_STATUS\r
128EFIAPI\r
129RamDiskBlkIoReadBlocks (\r
130 IN EFI_BLOCK_IO_PROTOCOL *This,\r
131 IN UINT32 MediaId,\r
132 IN EFI_LBA Lba,\r
133 IN UINTN BufferSize,\r
134 OUT VOID *Buffer\r
135 )\r
136{\r
137 RAM_DISK_PRIVATE_DATA *PrivateData;\r
138 UINTN NumberOfBlocks;\r
139\r
0feca62c
HW
140 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);\r
141\r
142 if (MediaId != PrivateData->Media.MediaId) {\r
143 return EFI_MEDIA_CHANGED;\r
144 }\r
145\r
20752cb8
HW
146 if (Buffer == NULL) {\r
147 return EFI_INVALID_PARAMETER;\r
148 }\r
149\r
150 if (BufferSize == 0) {\r
151 return EFI_SUCCESS;\r
152 }\r
153\r
20752cb8
HW
154 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {\r
155 return EFI_BAD_BUFFER_SIZE;\r
156 }\r
157\r
158 if (Lba > PrivateData->Media.LastBlock) {\r
159 return EFI_INVALID_PARAMETER;\r
160 }\r
161\r
162 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;\r
163 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {\r
164 return EFI_INVALID_PARAMETER;\r
165 }\r
166\r
167 CopyMem (\r
168 Buffer,\r
169 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),\r
170 BufferSize\r
171 );\r
172\r
173 return EFI_SUCCESS;\r
174}\r
175\r
176\r
177/**\r
178 Write BufferSize bytes from Lba into Buffer.\r
179\r
180 @param[in] This Indicates a pointer to the calling context.\r
181 @param[in] MediaId The media ID that the write request is for.\r
182 @param[in] Lba The starting logical block address to be written.\r
183 The caller is responsible for writing to only\r
184 legitimate locations.\r
185 @param[in] BufferSize Size of Buffer, must be a multiple of device block\r
186 size.\r
187 @param[in] Buffer A pointer to the source buffer for the data.\r
188\r
189 @retval EFI_SUCCESS The data was written correctly to the device.\r
190 @retval EFI_WRITE_PROTECTED The device can not be written to.\r
191 @retval EFI_DEVICE_ERROR The device reported an error while performing\r
192 the write.\r
193 @retval EFI_NO_MEDIA There is no media in the device.\r
194 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current\r
195 device.\r
196 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block\r
197 size of the device.\r
198 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not\r
199 valid, or the buffer is not on proper alignment.\r
200\r
201**/\r
202EFI_STATUS\r
203EFIAPI\r
204RamDiskBlkIoWriteBlocks (\r
205 IN EFI_BLOCK_IO_PROTOCOL *This,\r
206 IN UINT32 MediaId,\r
207 IN EFI_LBA Lba,\r
208 IN UINTN BufferSize,\r
209 IN VOID *Buffer\r
210 )\r
211{\r
212 RAM_DISK_PRIVATE_DATA *PrivateData;\r
213 UINTN NumberOfBlocks;\r
214\r
20752cb8
HW
215 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);\r
216\r
217 if (MediaId != PrivateData->Media.MediaId) {\r
218 return EFI_MEDIA_CHANGED;\r
219 }\r
220\r
221 if (TRUE == PrivateData->Media.ReadOnly) {\r
222 return EFI_WRITE_PROTECTED;\r
223 }\r
224\r
0feca62c
HW
225 if (Buffer == NULL) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
229 if (BufferSize == 0) {\r
230 return EFI_SUCCESS;\r
231 }\r
232\r
20752cb8
HW
233 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {\r
234 return EFI_BAD_BUFFER_SIZE;\r
235 }\r
236\r
237 if (Lba > PrivateData->Media.LastBlock) {\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240\r
241 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;\r
242 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {\r
243 return EFI_INVALID_PARAMETER;\r
244 }\r
245\r
246 CopyMem (\r
247 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),\r
248 Buffer,\r
249 BufferSize\r
250 );\r
251\r
252 return EFI_SUCCESS;\r
253}\r
254\r
255\r
256/**\r
257 Flush the Block Device.\r
258\r
259 @param[in] This Indicates a pointer to the calling context.\r
260\r
261 @retval EFI_SUCCESS All outstanding data was written to the device.\r
262 @retval EFI_DEVICE_ERROR The device reported an error while writting\r
263 back the data\r
264 @retval EFI_NO_MEDIA There is no media in the device.\r
265\r
266**/\r
267EFI_STATUS\r
268EFIAPI\r
269RamDiskBlkIoFlushBlocks (\r
270 IN EFI_BLOCK_IO_PROTOCOL *This\r
271 )\r
272{\r
273 return EFI_SUCCESS;\r
274}\r
216fefa3
HW
275\r
276\r
277/**\r
278 Resets the block device hardware.\r
279\r
280 @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.\r
281 @param[in] ExtendedVerification The flag about if extend verificate.\r
282\r
283 @retval EFI_SUCCESS The device was reset.\r
284 @retval EFI_DEVICE_ERROR The block device is not functioning correctly\r
285 and could not be reset.\r
286\r
287**/\r
288EFI_STATUS\r
289EFIAPI\r
290RamDiskBlkIo2Reset (\r
291 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
292 IN BOOLEAN ExtendedVerification\r
293 )\r
294{\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298\r
299/**\r
300 Reads the requested number of blocks from the device.\r
301\r
302 @param[in] This Indicates a pointer to the calling context.\r
303 @param[in] MediaId The media ID that the read request is for.\r
304 @param[in] Lba The starting logical block address to read\r
305 from on the device.\r
306 @param[in, out] Token A pointer to the token associated with the\r
307 transaction.\r
308 @param[in] BufferSize The size of the Buffer in bytes. This must be\r
309 a multiple of the intrinsic block size of the\r
310 device.\r
311 @param[out] Buffer A pointer to the destination buffer for the\r
312 data. The caller is responsible for either\r
313 having implicit or explicit ownership of the\r
314 buffer.\r
315\r
316 @retval EFI_SUCCESS The read request was queued if Token->Event\r
317 is not NULL. The data was read correctly from\r
318 the device if the Token->Event is NULL.\r
319 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
320 to perform the read operation.\r
321 @retval EFI_NO_MEDIA There is no media in the device.\r
322 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
323 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
324 the intrinsic block size of the device.\r
325 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
326 valid, or the buffer is not on proper\r
327 alignment.\r
328 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
329 lack of resources.\r
330\r
331**/\r
332EFI_STATUS\r
333EFIAPI\r
334RamDiskBlkIo2ReadBlocksEx (\r
335 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
336 IN UINT32 MediaId,\r
337 IN EFI_LBA Lba,\r
338 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
339 IN UINTN BufferSize,\r
340 OUT VOID *Buffer\r
341 )\r
342{\r
343 RAM_DISK_PRIVATE_DATA *PrivateData;\r
344 EFI_STATUS Status;\r
345\r
346 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
347\r
348 Status = RamDiskBlkIoReadBlocks (\r
349 &PrivateData->BlockIo,\r
350 MediaId,\r
351 Lba,\r
352 BufferSize,\r
353 Buffer\r
354 );\r
355 if (EFI_ERROR (Status)) {\r
356 return Status;\r
357 }\r
358\r
359 //\r
360 // If caller's event is given, signal it after the memory read completes.\r
361 //\r
362 if ((Token != NULL) && (Token->Event != NULL)) {\r
363 Token->TransactionStatus = EFI_SUCCESS;\r
364 gBS->SignalEvent (Token->Event);\r
365 }\r
366\r
367 return EFI_SUCCESS;\r
368}\r
369\r
370\r
371/**\r
372 Writes a specified number of blocks to the device.\r
373\r
374 @param[in] This Indicates a pointer to the calling context.\r
375 @param[in] MediaId The media ID that the write request is for.\r
376 @param[in] Lba The starting logical block address to be\r
377 written. The caller is responsible for\r
378 writing to only legitimate locations.\r
379 @param[in, out] Token A pointer to the token associated with the\r
380 transaction.\r
381 @param[in] BufferSize The size in bytes of Buffer. This must be a\r
382 multiple of the intrinsic block size of the\r
383 device.\r
384 @param[in] Buffer A pointer to the source buffer for the data.\r
385\r
386 @retval EFI_SUCCESS The write request was queued if Event is not\r
387 NULL. The data was written correctly to the\r
388 device if the Event is NULL.\r
389 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
390 @retval EFI_NO_MEDIA There is no media in the device.\r
391 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
392 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
393 to perform the write operation.\r
394 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
395 the intrinsic block size of the device.\r
396 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not\r
397 valid, or the buffer is not on proper\r
398 alignment.\r
399 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
400 lack of resources.\r
401\r
402**/\r
403EFI_STATUS\r
404EFIAPI\r
405RamDiskBlkIo2WriteBlocksEx (\r
406 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
407 IN UINT32 MediaId,\r
408 IN EFI_LBA Lba,\r
409 IN OUT EFI_BLOCK_IO2_TOKEN *Token,\r
410 IN UINTN BufferSize,\r
411 IN VOID *Buffer\r
412 )\r
413{\r
414 RAM_DISK_PRIVATE_DATA *PrivateData;\r
415 EFI_STATUS Status;\r
416\r
417 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
418\r
419 Status = RamDiskBlkIoWriteBlocks (\r
420 &PrivateData->BlockIo,\r
421 MediaId,\r
422 Lba,\r
423 BufferSize,\r
424 Buffer\r
425 );\r
426 if (EFI_ERROR (Status)) {\r
427 return Status;\r
428 }\r
429\r
430 //\r
431 // If caller's event is given, signal it after the memory write completes.\r
432 //\r
433 if ((Token != NULL) && (Token->Event != NULL)) {\r
434 Token->TransactionStatus = EFI_SUCCESS;\r
435 gBS->SignalEvent (Token->Event);\r
436 }\r
437\r
438 return EFI_SUCCESS;\r
439}\r
440\r
441\r
442/**\r
443 Flushes all modified data to a physical block device.\r
444\r
445 @param[in] This Indicates a pointer to the calling context.\r
446 @param[in, out] Token A pointer to the token associated with the\r
447 transaction.\r
448\r
449 @retval EFI_SUCCESS The flush request was queued if Event is not\r
450 NULL. All outstanding data was written\r
451 correctly to the device if the Event is NULL.\r
452 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
453 to write data.\r
454 @retval EFI_WRITE_PROTECTED The device cannot be written to.\r
455 @retval EFI_NO_MEDIA There is no media in the device.\r
456 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
457 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a\r
458 lack of resources.\r
459\r
460**/\r
461EFI_STATUS\r
462EFIAPI\r
463RamDiskBlkIo2FlushBlocksEx (\r
464 IN EFI_BLOCK_IO2_PROTOCOL *This,\r
465 IN OUT EFI_BLOCK_IO2_TOKEN *Token\r
466 )\r
467{\r
468 RAM_DISK_PRIVATE_DATA *PrivateData;\r
469\r
470 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);\r
471\r
472 if (TRUE == PrivateData->Media.ReadOnly) {\r
473 return EFI_WRITE_PROTECTED;\r
474 }\r
475\r
476 //\r
477 // If caller's event is given, signal it directly.\r
478 //\r
479 if ((Token != NULL) && (Token->Event != NULL)) {\r
480 Token->TransactionStatus = EFI_SUCCESS;\r
481 gBS->SignalEvent (Token->Event);\r
482 }\r
483\r
484 return EFI_SUCCESS;\r
485}\r