-
Notifications
You must be signed in to change notification settings - Fork 0
/
initrd.c
125 lines (111 loc) · 4.15 KB
/
initrd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// initrd.h -- Defines the interface for and structures relating to the
// initial ramdisk.
// Written for JamesM's kernel development tutorials.
#include "initrd.h"
initrd_header_t *initrd_header; // The header.
initrd_file_header_t *file_headers; // The list of file headers.
fs_node_t *initrd_root; // Our root directory node.
fs_node_t *initrd_dev; // We also add a directory node for /dev
// so we can mount devfs later.
fs_node_t *root_nodes; // List of file nodes.
u32int nroot_nodes; // Number of file nodes;
struct dirent dirent;
/**
Reads from a file in the initrd.
**/
static u32int initrd_read(fs_node_t *node, u32int offset, u32int size, u8int *buffer)
{
initrd_file_header_t header = file_headers[node->inode];
if(offset > header.length)
return 0;
if(offset + size > header.length)
size = header.length-offset;
memcpy(buffer, (u8int*)(header.offset + offset), size);
return size;
}
static struct dirent *initrd_readdir(fs_node_t *node, u32int index)
{
if(node == initrd_root && index == 0)
{
if(dirent.name && index == 0)
{
strcpy(dirent.name, "dev");
dirent.name[3] = 0; // Make sure the string is NULL - terminated.
dirent.ino = 0;
return &dirent;
}
}
if(index - 1 >= nroot_nodes)
return 0;
strcpy(dirent.name, root_nodes[index - 1].name);
dirent.name[strlen(root_nodes[index - 1].name)] = 0;
dirent.ino = root_nodes[index - 1].inode;
return &dirent;
}
static fs_node_t *initrd_finddir(fs_node_t *node, char *name)
{
if (node == initrd_root && !strcmp(name, "dev"))
return initrd_dev;
int i;
for (i = 0; i < nroot_nodes; i++)
if (!strcmp(name, root_nodes[i].name))
return &root_nodes[i];
return 0;
}
fs_node_t *initialise_initrd(u32int location)
{
// Initialise the main and file header pointers and populate the root directory.
initrd_header = (initrd_header_t *)location;
file_headers = (initrd_file_header_t *) (location + sizeof(initrd_header_t));
// Initialise the root directory.
initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
strcpy(initrd_root->name, "initrd");
initrd_root->mask = initrd_root->uid = initrd_root->gid = initrd_root->inode = initrd_root->length = 0;
initrd_root->flags = FS_DIRECTORY;
initrd_root->read = 0;
initrd_root->write = 0;
initrd_root->open = 0;
initrd_root->close = 0;
initrd_root->readdir = &initrd_readdir;
initrd_root->finddir = &initrd_finddir;
initrd_root->ptr = 0;
initrd_root->impl = 0;
// Initialise the /dev directory (required!)
initrd_dev = (fs_node_t*)kmalloc(sizeof(fs_node_t));
strcpy(initrd_dev->name, "dev");
initrd_dev->mask = initrd_dev->uid = initrd_dev->gid = initrd_dev->inode = initrd_dev->length = 0;
initrd_dev->flags = FS_DIRECTORY;
initrd_dev->read = 0;
initrd_dev->write = 0;
initrd_dev->open = 0;
initrd_dev->close = 0;
initrd_dev->readdir = &initrd_readdir;
initrd_dev->finddir = &initrd_finddir;
initrd_dev->ptr = 0;
initrd_dev->impl = 0;
// Start adding the files in the ramdisk.
root_nodes = (fs_node_t*)kmalloc(sizeof(fs_node_t) * initrd_header->nfiles);
nroot_nodes = initrd_header->nfiles;
// For every file...
int i;
for (i = 0; i < initrd_header->nfiles; i++)
{
// Edit the file's header - currently it holds the file offset
// relative to the start of the ramdisk. We want it relative to the start
// of memory.
file_headers[i].offset += location;
// Create a new file node.
strcpy((char*)root_nodes[i].name, (char*)&file_headers[i].name);
root_nodes[i].mask = root_nodes[i].uid = root_nodes[i].gid = 0;
root_nodes[i].length = file_headers[i].length;
root_nodes[i].inode = i;
root_nodes[i].flags = FS_FILE;
root_nodes[i].read = &initrd_read;
root_nodes[i].write = 0;
root_nodes[i].readdir = 0;
root_nodes[i].finddir = 0;
root_nodes[i].open = 0;
root_nodes[i].close = 0;
root_nodes[i].impl = 0;
}
}