ramdisk.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. ramdisk.c
  5. Abstract:
  6. This module implements support for creating a Block I/O protocol from a
  7. RAM Disk device.
  8. Author:
  9. Evan Green 3-Apr-2014
  10. Environment:
  11. Firmware
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "ueficore.h"
  17. #include <minoca/uefi/protocol/ramdisk.h>
  18. #include <minoca/uefi/protocol/blockio.h>
  19. //
  20. // --------------------------------------------------------------------- Macros
  21. //
  22. //
  23. // This macro converts from a block I/O protocol to the RAM disk context.
  24. //
  25. #define EFI_RAM_DISK_FROM_THIS(_BlockIo) \
  26. PARENT_STRUCTURE(_BlockIo, EFI_RAM_DISK_CONTEXT, BlockIo);
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. #define EFI_RAM_DISK_MAGIC 0x444D4152 // 'DMAR'
  31. #define EFI_RAM_DISK_BLOCK_SIZE 512
  32. //
  33. // ------------------------------------------------------ Data Type Definitions
  34. //
  35. /*++
  36. Structure Description:
  37. This structure describes the RAM disk device context.
  38. Members:
  39. Magic - Stores the magic constand EFI_RAM_DISK_MAGIC.
  40. Handle - Stores the handle to the block I/O device.
  41. DevicePath - Stores a pointer to the device path.
  42. BlockCount - Stores the cached block count of the media.
  43. RamDisk - Stores the instance of the RAM disk protocol.
  44. BlockIo - Stores the block I/O protocol.
  45. Media - Stores the block I/O media information.
  46. --*/
  47. typedef struct _EFI_RAM_DISK_CONTEXT {
  48. UINT32 Magic;
  49. EFI_HANDLE Handle;
  50. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  51. UINT64 BlockCount;
  52. EFI_RAM_DISK_PROTOCOL RamDisk;
  53. EFI_BLOCK_IO_PROTOCOL BlockIo;
  54. EFI_BLOCK_IO_MEDIA Media;
  55. } EFI_RAM_DISK_CONTEXT, *PEFI_RAM_DISK_CONTEXT;
  56. /*++
  57. Structure Description:
  58. This structure defines the SD OMAP4 block I/O device path.
  59. Members:
  60. DevicePath - Stores the standard vendor-specific device path.
  61. Base - Stores the base physical address of the RAM disk.
  62. --*/
  63. typedef struct _EFI_RAM_DISK_DEVICE_PATH_NODE {
  64. VENDOR_DEVICE_PATH DevicePath;
  65. EFI_PHYSICAL_ADDRESS Base;
  66. } EFI_RAM_DISK_DEVICE_PATH_NODE, *PEFI_RAM_DISK_DEVICE_PATH_NODE;
  67. /*++
  68. Structure Description:
  69. This structure defines the RAM disk device path format.
  70. Members:
  71. Disk - Stores the RAM disk device path node.
  72. End - Stores the end device path node.
  73. --*/
  74. typedef struct _EFI_RAM_DISK_DEVICE_PATH {
  75. EFI_RAM_DISK_DEVICE_PATH_NODE Disk;
  76. EFI_DEVICE_PATH_PROTOCOL End;
  77. } PACKED EFI_RAM_DISK_DEVICE_PATH, *PEFI_RAM_DISK_DEVICE_PATH;
  78. //
  79. // ----------------------------------------------- Internal Function Prototypes
  80. //
  81. EFIAPI
  82. EFI_STATUS
  83. EfipRamDiskReset (
  84. EFI_BLOCK_IO_PROTOCOL *This,
  85. BOOLEAN ExtendedVerification
  86. );
  87. EFIAPI
  88. EFI_STATUS
  89. EfipRamDiskReadBlocks (
  90. EFI_BLOCK_IO_PROTOCOL *This,
  91. UINT32 MediaId,
  92. EFI_LBA Lba,
  93. UINTN BufferSize,
  94. VOID *Buffer
  95. );
  96. EFIAPI
  97. EFI_STATUS
  98. EfipRamDiskWriteBlocks (
  99. EFI_BLOCK_IO_PROTOCOL *This,
  100. UINT32 MediaId,
  101. EFI_LBA Lba,
  102. UINTN BufferSize,
  103. VOID *Buffer
  104. );
  105. EFIAPI
  106. EFI_STATUS
  107. EfipRamDiskFlushBlocks (
  108. EFI_BLOCK_IO_PROTOCOL *This
  109. );
  110. //
  111. // -------------------------------------------------------------------- Globals
  112. //
  113. EFI_RAM_DISK_DEVICE_PATH EfiRamDiskDevicePathTemplate = {
  114. {
  115. {
  116. {
  117. HARDWARE_DEVICE_PATH,
  118. HW_VENDOR_DP,
  119. sizeof(EFI_RAM_DISK_DEVICE_PATH_NODE)
  120. },
  121. EFI_RAM_DISK_PROTOCOL_GUID,
  122. },
  123. 0
  124. },
  125. {
  126. END_DEVICE_PATH_TYPE,
  127. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  128. END_DEVICE_PATH_LENGTH
  129. }
  130. };
  131. EFI_GUID EfiRamDiskProtocolGuid = EFI_RAM_DISK_PROTOCOL_GUID;
  132. //
  133. // ------------------------------------------------------------------ Functions
  134. //
  135. EFI_STATUS
  136. EfiCoreEnumerateRamDisk (
  137. EFI_PHYSICAL_ADDRESS Base,
  138. UINT64 Size
  139. )
  140. /*++
  141. Routine Description:
  142. This routine enumerates a RAM disk at the given address.
  143. Arguments:
  144. Base - Supplies the base physical address of the RAM disk.
  145. Size - Supplies the size of the RAM disk.
  146. Return Value:
  147. EFI Status code.
  148. --*/
  149. {
  150. PEFI_RAM_DISK_CONTEXT Context;
  151. EFI_RAM_DISK_DEVICE_PATH *DevicePath;
  152. EFI_STATUS Status;
  153. Context = NULL;
  154. DevicePath = NULL;
  155. //
  156. // Allocate the context structure.
  157. //
  158. Status = EfiAllocatePool(EfiBootServicesData,
  159. sizeof(EFI_RAM_DISK_CONTEXT),
  160. (VOID **)&Context);
  161. if (EFI_ERROR(Status)) {
  162. goto EnumerateRamDiskEnd;
  163. }
  164. EfiSetMem(Context, sizeof(EFI_RAM_DISK_CONTEXT), 0);
  165. Context->Magic = EFI_RAM_DISK_MAGIC;
  166. //
  167. // Allocate the device path.
  168. //
  169. Status = EfiAllocatePool(EfiBootServicesData,
  170. sizeof(EFI_RAM_DISK_DEVICE_PATH),
  171. (VOID **)(&DevicePath));
  172. if (EFI_ERROR(Status)) {
  173. goto EnumerateRamDiskEnd;
  174. }
  175. EfiCopyMem(DevicePath,
  176. &EfiRamDiskDevicePathTemplate,
  177. sizeof(EFI_RAM_DISK_DEVICE_PATH));
  178. DevicePath->Disk.Base = Base;
  179. Context->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
  180. Context->BlockCount = (Size + (EFI_RAM_DISK_BLOCK_SIZE - 1)) /
  181. EFI_RAM_DISK_BLOCK_SIZE;
  182. Context->RamDisk.Revision = EFI_RAM_DISK_PROTOCOL_REVISION;
  183. Context->RamDisk.Base = Base;
  184. Context->RamDisk.Length = Size;
  185. Context->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
  186. Context->BlockIo.Media = &(Context->Media);
  187. Context->BlockIo.Reset = EfipRamDiskReset;
  188. Context->BlockIo.ReadBlocks = EfipRamDiskReadBlocks;
  189. Context->BlockIo.WriteBlocks = EfipRamDiskWriteBlocks;
  190. Context->BlockIo.FlushBlocks = EfipRamDiskFlushBlocks;
  191. Context->Media.MediaId = 1;
  192. Context->Media.MediaPresent = 1;
  193. Context->Media.BlockSize = EFI_RAM_DISK_BLOCK_SIZE;
  194. Context->Media.LastBlock = Context->BlockCount - 1;
  195. Status = EfiInstallMultipleProtocolInterfaces(&(Context->Handle),
  196. &EfiBlockIoProtocolGuid,
  197. &(Context->BlockIo),
  198. &EfiDevicePathProtocolGuid,
  199. Context->DevicePath,
  200. &EfiRamDiskProtocolGuid,
  201. &(Context->RamDisk),
  202. NULL);
  203. Status = EFI_SUCCESS;
  204. EnumerateRamDiskEnd:
  205. if (EFI_ERROR(Status)) {
  206. if (Context != NULL) {
  207. EfiFreePool(Context);
  208. }
  209. if (DevicePath != NULL) {
  210. EfiFreePool(DevicePath);
  211. }
  212. }
  213. return Status;
  214. }
  215. //
  216. // --------------------------------------------------------- Internal Functions
  217. //
  218. EFIAPI
  219. EFI_STATUS
  220. EfipRamDiskReset (
  221. EFI_BLOCK_IO_PROTOCOL *This,
  222. BOOLEAN ExtendedVerification
  223. )
  224. /*++
  225. Routine Description:
  226. This routine resets the block device.
  227. Arguments:
  228. This - Supplies a pointer to the protocol instance.
  229. ExtendedVerification - Supplies a boolean indicating whether or not the
  230. driver should perform diagnostics on reset.
  231. Return Value:
  232. EFI_SUCCESS on success.
  233. EFI_DEVICE_ERROR if the device had an error and could not complete the
  234. request.
  235. --*/
  236. {
  237. return EFI_SUCCESS;
  238. }
  239. EFIAPI
  240. EFI_STATUS
  241. EfipRamDiskReadBlocks (
  242. EFI_BLOCK_IO_PROTOCOL *This,
  243. UINT32 MediaId,
  244. EFI_LBA Lba,
  245. UINTN BufferSize,
  246. VOID *Buffer
  247. )
  248. /*++
  249. Routine Description:
  250. This routine performs a block I/O read from the device.
  251. Arguments:
  252. This - Supplies a pointer to the protocol instance.
  253. MediaId - Supplies the media identifier, which changes each time the media
  254. is replaced.
  255. Lba - Supplies the logical block address of the read.
  256. BufferSize - Supplies the size of the buffer in bytes.
  257. Buffer - Supplies the buffer where the read data will be returned.
  258. Return Value:
  259. EFI_SUCCESS on success.
  260. EFI_DEVICE_ERROR if the device had an error and could not complete the
  261. request.
  262. EFI_NO_MEDIA if there is no media in the device.
  263. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  264. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  265. size.
  266. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  267. or the buffer is not properly aligned.
  268. --*/
  269. {
  270. EFI_RAM_DISK_CONTEXT *Context;
  271. VOID *DiskBuffer;
  272. Context = EFI_RAM_DISK_FROM_THIS(This);
  273. if (Lba + (BufferSize / EFI_RAM_DISK_BLOCK_SIZE) > Context->BlockCount) {
  274. return EFI_INVALID_PARAMETER;
  275. }
  276. if ((BufferSize % EFI_RAM_DISK_BLOCK_SIZE) != 0) {
  277. return EFI_BAD_BUFFER_SIZE;
  278. }
  279. DiskBuffer = (VOID *)(UINTN)(Context->RamDisk.Base +
  280. (Lba * EFI_RAM_DISK_BLOCK_SIZE));
  281. EfiCopyMem(Buffer, DiskBuffer, BufferSize);
  282. return EFI_SUCCESS;
  283. }
  284. EFIAPI
  285. EFI_STATUS
  286. EfipRamDiskWriteBlocks (
  287. EFI_BLOCK_IO_PROTOCOL *This,
  288. UINT32 MediaId,
  289. EFI_LBA Lba,
  290. UINTN BufferSize,
  291. VOID *Buffer
  292. )
  293. /*++
  294. Routine Description:
  295. This routine performs a block I/O write to the device.
  296. Arguments:
  297. This - Supplies a pointer to the protocol instance.
  298. MediaId - Supplies the media identifier, which changes each time the media
  299. is replaced.
  300. Lba - Supplies the logical block address of the write.
  301. BufferSize - Supplies the size of the buffer in bytes.
  302. Buffer - Supplies the buffer containing the data to write.
  303. Return Value:
  304. EFI_SUCCESS on success.
  305. EFI_WRITE_PROTECTED if the device cannot be written to.
  306. EFI_DEVICE_ERROR if the device had an error and could not complete the
  307. request.
  308. EFI_NO_MEDIA if there is no media in the device.
  309. EFI_MEDIA_CHANGED if the media ID does not match the current device.
  310. EFI_BAD_BUFFER_SIZE if the buffer was not a multiple of the device block
  311. size.
  312. EFI_INVALID_PARAMETER if the read request contains LBAs that are not valid,
  313. or the buffer is not properly aligned.
  314. --*/
  315. {
  316. EFI_RAM_DISK_CONTEXT *Context;
  317. VOID *DiskBuffer;
  318. Context = EFI_RAM_DISK_FROM_THIS(This);
  319. if (Lba + (BufferSize / EFI_RAM_DISK_BLOCK_SIZE) >= Context->BlockCount) {
  320. return EFI_INVALID_PARAMETER;
  321. }
  322. if ((BufferSize % EFI_RAM_DISK_BLOCK_SIZE) != 0) {
  323. return EFI_BAD_BUFFER_SIZE;
  324. }
  325. DiskBuffer = (VOID *)(UINTN)(Context->RamDisk.Base +
  326. (Lba * EFI_RAM_DISK_BLOCK_SIZE));
  327. EfiCopyMem(DiskBuffer, Buffer, BufferSize);
  328. return EFI_SUCCESS;
  329. }
  330. EFIAPI
  331. EFI_STATUS
  332. EfipRamDiskFlushBlocks (
  333. EFI_BLOCK_IO_PROTOCOL *This
  334. )
  335. /*++
  336. Routine Description:
  337. This routine flushes the block device.
  338. Arguments:
  339. This - Supplies a pointer to the protocol instance.
  340. Return Value:
  341. EFI_SUCCESS on success.
  342. EFI_DEVICE_ERROR if the device had an error and could not complete the
  343. request.
  344. EFI_NO_MEDIA if there is no media in the device.
  345. --*/
  346. {
  347. return EFI_SUCCESS;
  348. }