ramdisk.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2014 Kevin Lange
  5. *
  6. * Ramdisk driver.
  7. *
  8. * Provide raw block access to files loaded into kernel memory.
  9. */
  10. #include <kernel/system.h>
  11. #include <kernel/logging.h>
  12. #include <kernel/module.h>
  13. #include <kernel/fs.h>
  14. #include <kernel/printf.h>
  15. #include <kernel/mem.h>
  16. static uint32_t read_ramdisk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
  17. static uint32_t write_ramdisk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
  18. static void open_ramdisk(fs_node_t *node, unsigned int flags);
  19. static void close_ramdisk(fs_node_t *node);
  20. static uint32_t read_ramdisk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  21. if (offset > node->length) {
  22. return 0;
  23. }
  24. if (offset + size > node->length) {
  25. unsigned int i = node->length - offset;
  26. size = i;
  27. }
  28. memcpy(buffer, (void *)(node->inode + offset), size);
  29. return size;
  30. }
  31. static uint32_t write_ramdisk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  32. if (offset > node->length) {
  33. return 0;
  34. }
  35. if (offset + size > node->length) {
  36. unsigned int i = node->length - offset;
  37. size = i;
  38. }
  39. memcpy((void *)(node->inode + offset), buffer, size);
  40. return size;
  41. }
  42. static void open_ramdisk(fs_node_t * node, unsigned int flags) {
  43. return;
  44. }
  45. static void close_ramdisk(fs_node_t * node) {
  46. return;
  47. }
  48. static int ioctl_ramdisk(fs_node_t * node, int request, void * argp) {
  49. switch (request) {
  50. case 0x4001:
  51. if (current_process->user != 0) {
  52. return -EPERM;
  53. } else {
  54. /* Clear all of the memory used by this ramdisk */
  55. for (uintptr_t i = node->inode; i < node->inode + node->length; i += 0x1000) {
  56. clear_frame(i);
  57. }
  58. /* Mark the file length as 0 */
  59. node->length = 0;
  60. return 0;
  61. }
  62. default:
  63. return -EINVAL;
  64. }
  65. }
  66. static fs_node_t * ramdisk_device_create(int device_number, uintptr_t location, size_t size) {
  67. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  68. memset(fnode, 0x00, sizeof(fs_node_t));
  69. fnode->inode = location;
  70. sprintf(fnode->name, "ram%d", device_number);
  71. fnode->uid = 0;
  72. fnode->gid = 0;
  73. fnode->mask = 0660;
  74. fnode->length = size;
  75. fnode->flags = FS_BLOCKDEVICE;
  76. fnode->read = read_ramdisk;
  77. fnode->write = write_ramdisk;
  78. fnode->open = open_ramdisk;
  79. fnode->close = close_ramdisk;
  80. fnode->ioctl = ioctl_ramdisk;
  81. return fnode;
  82. }
  83. static int last_device_number = 0;
  84. fs_node_t * ramdisk_mount(uintptr_t location, size_t size) {
  85. fs_node_t * ramdisk = ramdisk_device_create(last_device_number, location, size);
  86. if (ramdisk) {
  87. char tmp[64];
  88. sprintf(tmp, "/dev/%s", ramdisk->name);
  89. vfs_mount(tmp, ramdisk);
  90. last_device_number += 1;
  91. return ramdisk;
  92. }
  93. return NULL;
  94. }