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