1 | /*␊ |
2 | * Supplemental ramdisk functions for the multiboot ramdisk driver.␊ |
3 | * Copyright 2009 Tamas Kosarszky. All rights reserved.␊ |
4 | *␊ |
5 | */␊ |
6 | ␊ |
7 | #include "boot.h"␊ |
8 | #include "bootstruct.h"␊ |
9 | #include "multiboot.h"␊ |
10 | #include "ramdisk.h"␊ |
11 | ␊ |
12 | struct multiboot_info * gRAMDiskMI = NULL;␊ |
13 | ␊ |
14 | // gRAMDiskVolume holds the bvr for the mounted ramdisk image.␊ |
15 | BVRef gRAMDiskVolume = NULL;␊ |
16 | bool gRAMDiskBTAliased = false;␊ |
17 | char gRAMDiskFile[512];␊ |
18 | ␊ |
19 | ␊ |
20 | // Notify OS X that a ramdisk has been loaded. XNU will attach this to /dev/md0␊ |
21 | void md0Ramdisk()␊ |
22 | {␊ |
23 | ␉RAMDiskParam ramdiskPtr;␊ |
24 | ␉char* filename = 0;␊ |
25 | ␉int fh = 0;␊ |
26 | ␉␊ |
27 | ␉// Look for ramdisk at Postboot.img␊ |
28 | ␉filename = "bt(0,0)/Postboot.img";␊ |
29 | ␉if((fh = open(filename, 0)) == -1)␊ |
30 | ␉{␊ |
31 | ␉␉filename = "/Postboot.img";␉// Check rd(0,0) if not in bt(0,0)␊ |
32 | ␉␉fh = open(filename, 0);␊ |
33 | ␊ |
34 | ␉}␊ |
35 | ␉␊ |
36 | ␉␊ |
37 | ␉if (fh != -1)␊ |
38 | ␉{␊ |
39 | ␉␉verbose("Loading ramdisk %s\n", filename);␊ |
40 | ␊ |
41 | ␉␉ramdiskPtr.size = file_size(fh);␊ |
42 | ␉␉ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size);␊ |
43 | ␉␉␊ |
44 | ␉␉if(ramdiskPtr.size && ramdiskPtr.base)␊ |
45 | ␉␉{␊ |
46 | ␉␉␉// Read new ramdisk image contents in kernel memory.␊ |
47 | ␉␉␉if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size)␊ |
48 | ␉␉␉{␊ |
49 | ␉␉␉␉AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid);␊ |
50 | ␉␉␉␉Node* node = DT__FindNode("/chosen/memory-map", false);␊ |
51 | ␉␉␉␉if(node != NULL)␊ |
52 | ␉␉␉␉{␊ |
53 | ␉␉␉␉␉DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr);␉␉␊ |
54 | ␉␉␉␉␉␊ |
55 | ␉␉␉␉}␊ |
56 | ␉␉␉␉else␊ |
57 | ␉␉␉␉{␊ |
58 | ␉␉␉␉␉verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename);␊ |
59 | ␉␉␉␉}␊ |
60 | ␉␉␉␉␊ |
61 | ␉␉␉}␊ |
62 | ␉␉␉else {␊ |
63 | ␉␉␉␉verbose("Unable to read ramdisk %s\n", filename);␊ |
64 | ␉␉␉}␊ |
65 | ␉␉␉␊ |
66 | ␉␉} else {␊ |
67 | ␉␉␉verbose("Ramdisk %s is empty.\n", filename);␊ |
68 | ␉␉}␊ |
69 | ␉␉␊ |
70 | ␉␉␊ |
71 | ␉␉close(fh);␊ |
72 | ␉␉␊ |
73 | ␉}␊ |
74 | ␉else {␊ |
75 | ␉␉verbose("Unable to open %s\n", filename);␊ |
76 | ␉}␊ |
77 | }␊ |
78 | ␊ |
79 | ␊ |
80 | void umountRAMDisk()␊ |
81 | {␊ |
82 | if (gRAMDiskMI != NULL)␊ |
83 | {␊ |
84 | // Release ramdisk BVRef and DiskBVMap.␊ |
85 | struct DiskBVMap *oldMap = diskResetBootVolumes(0x100);␊ |
86 | CacheReset();␊ |
87 | diskFreeMap(oldMap);␊ |
88 | ␊ |
89 | // Free multiboot info and module structures.␊ |
90 | if ((void *)gRAMDiskMI->mi_mods_addr != NULL) free((void *)gRAMDiskMI->mi_mods_addr);␊ |
91 | if (gRAMDiskMI != NULL) free(gRAMDiskMI);␊ |
92 | ␊ |
93 | // Reset multiboot structures.␊ |
94 | gMI = gRAMDiskMI = NULL;␊ |
95 | *gRAMDiskFile = '\0';␊ |
96 | ␊ |
97 | // Release ramdisk driver hooks.␊ |
98 | p_get_ramdisk_info = NULL;␊ |
99 | p_ramdiskReadBytes = NULL;␊ |
100 | ␊ |
101 | printf("\nunmounting: done");␊ |
102 | }␊ |
103 | }␊ |
104 | ␊ |
105 | int mountRAMDisk(const char * param)␊ |
106 | {␊ |
107 | int fh = 0, ramDiskSize;␊ |
108 | int error = 0;␊ |
109 | ␊ |
110 | // Get file handle for ramdisk file.␊ |
111 | fh = open(param, 0);␊ |
112 | if (fh != -1)␊ |
113 | {␊ |
114 | ␉printf("\nreading ramdisk image: %s", param);␊ |
115 | ␊ |
116 | ␉ramDiskSize = file_size(fh);␊ |
117 | if (ramDiskSize > 0)␊ |
118 | {␊ |
119 | // Unmount previously mounted image if exists.␊ |
120 | umountRAMDisk();␊ |
121 | ␊ |
122 | // Read new ramdisk image contents into PREBOOT_DATA area.␊ |
123 | if (read(fh, (char *)PREBOOT_DATA, ramDiskSize) != ramDiskSize) error = -1;␊ |
124 | }␊ |
125 | else error = -1;␊ |
126 | ␊ |
127 | close(fh);␊ |
128 | }␊ |
129 | else error = -1;␊ |
130 | ␊ |
131 | if (error == 0)␊ |
132 | {␊ |
133 | // Save filename in gRAMDiskFile to display information.␊ |
134 | strcpy(gRAMDiskFile, param);␊ |
135 | ␊ |
136 | // Set gMI as well for the multiboot ramdisk driver hook.␊ |
137 | gMI = gRAMDiskMI = malloc(sizeof(multiboot_info));␊ |
138 | struct multiboot_module * ramdisk_module = malloc(sizeof(multiboot_module));␊ |
139 | ␊ |
140 | // Fill in multiboot info and module structures.␊ |
141 | if (gRAMDiskMI != NULL && ramdisk_module != NULL)␊ |
142 | {␊ |
143 | gRAMDiskMI->mi_mods_count = 1;␊ |
144 | gRAMDiskMI->mi_mods_addr = (uint32_t)ramdisk_module;␊ |
145 | ramdisk_module->mm_mod_start = PREBOOT_DATA;␊ |
146 | ramdisk_module->mm_mod_end = PREBOOT_DATA + ramDiskSize;␊ |
147 | ␊ |
148 | // Set ramdisk driver hooks.␊ |
149 | p_get_ramdisk_info = &multiboot_get_ramdisk_info;␊ |
150 | p_ramdiskReadBytes = &multibootRamdiskReadBytes;␊ |
151 | ␊ |
152 | int partCount; // unused␊ |
153 | // Save bvr of the mounted image.␊ |
154 | gRAMDiskVolume = diskScanBootVolumes(0x100, &partCount);␊ |
155 | if(gRAMDiskVolume == NULL)␊ |
156 | {␊ |
157 | umountRAMDisk();␊ |
158 | printf("\nRamdisk contains no partitions.");␊ |
159 | }␊ |
160 | else␊ |
161 | {␊ |
162 | char dirSpec[128];␊ |
163 | ␊ |
164 | // Reading ramdisk configuration.␊ |
165 | strcpy(dirSpec, RAMDISKCONFIG_FILENAME);␊ |
166 | ␊ |
167 | if (loadConfigFile(dirSpec, &bootInfo->ramdiskConfig) == 0)␊ |
168 | {␊ |
169 | getBoolForKey("BTAlias", &gRAMDiskBTAliased, &bootInfo->ramdiskConfig);␊ |
170 | }␊ |
171 | else␊ |
172 | {␊ |
173 | printf("\nno ramdisk config...\n");␊ |
174 | }␊ |
175 | ␊ |
176 | printf("\nmounting: done");␊ |
177 | }␊ |
178 | }␊ |
179 | ␊ |
180 | }␊ |
181 | ␊ |
182 | return error;␊ |
183 | }␊ |
184 | ␊ |
185 | void setRAMDiskBTHook(bool mode)␊ |
186 | {␊ |
187 | gRAMDiskBTAliased = mode;␊ |
188 | if (mode) {␊ |
189 | printf("\nEnabled bt(0,0) alias.");␊ |
190 | } else {␊ |
191 | printf("\nDisabled bt(0,0) alias.");␊ |
192 | }␊ |
193 | }␊ |
194 | ␊ |
195 | void showInfoRAMDisk(void)␊ |
196 | {␊ |
197 | int len;␊ |
198 | const char *val;␊ |
199 | ␊ |
200 | if (gRAMDiskMI != NULL)␊ |
201 | {␊ |
202 | struct multiboot_module * ramdisk_module = (void *)gRAMDiskMI->mi_mods_addr;␊ |
203 | ␊ |
204 | printf("\nfile: %s %d", gRAMDiskFile,␊ |
205 | ramdisk_module->mm_mod_end - ramdisk_module->mm_mod_start);␊ |
206 | printf("\nalias: %s", gRAMDiskBTAliased ? "enabled" : "disabled");␊ |
207 | ␊ |
208 | // Display ramdisk information if available.␊ |
209 | ␊ |
210 | if (getValueForKey("Info", &val, &len, &bootInfo->ramdiskConfig))␊ |
211 | printf("\ninfo: %s", val);␊ |
212 | else␊ |
213 | printf("\nramdisk info not available.");␊ |
214 | ␊ |
215 | }␊ |
216 | else␊ |
217 | {␊ |
218 | printf("\nNo ramdisk mounted.");␊ |
219 | }␊ |
220 | }␊ |
221 | ␊ |
222 | int loadPrebootRAMDisk()␊ |
223 | {␊ |
224 | mountRAMDisk("bt(0,0)/Extra/Preboot.dmg");␊ |
225 | if (gRAMDiskMI != NULL)␊ |
226 | {␊ |
227 | printf("\n");␊ |
228 | return 0;␊ |
229 | }␊ |
230 | else␊ |
231 | {␊ |
232 | return -1;␊ |
233 | }␊ |
234 | }␊ |
235 | ␊ |
236 | void processRAMDiskCommand(char ** argPtr, const char * cmd)␊ |
237 | {␊ |
238 | char * ptr = *argPtr;␊ |
239 | char param[1024];␊ |
240 | getNextArg(&ptr, param);␊ |
241 | ␊ |
242 | if (strcmp(cmd, "m") == 0)␊ |
243 | {␊ |
244 | mountRAMDisk(param);␊ |
245 | sleep(2);␊ |
246 | }␊ |
247 | else if (strcmp(cmd, "u") == 0)␊ |
248 | {␊ |
249 | umountRAMDisk();␊ |
250 | sleep(2);␊ |
251 | }␊ |
252 | else if (strcmp(cmd, "e") == 0)␊ |
253 | {␊ |
254 | setRAMDiskBTHook(1);␊ |
255 | sleep(2);␊ |
256 | }␊ |
257 | else if (strcmp(cmd, "d") == 0)␊ |
258 | {␊ |
259 | setRAMDiskBTHook(0);␊ |
260 | sleep(2);␊ |
261 | }␊ |
262 | else if (strcmp(cmd, "i") == 0)␊ |
263 | {␊ |
264 | setActiveDisplayPage(1);␊ |
265 | clearScreenRows(0, 24);␊ |
266 | setCursorPosition(0, 0, 1);␊ |
267 | showInfoRAMDisk();␊ |
268 | printf("\n\nPress any key to continue.\n");␊ |
269 | getc();␊ |
270 | setActiveDisplayPage(0);␊ |
271 | }␊ |
272 | else␊ |
273 | {␊ |
274 | setActiveDisplayPage(1);␊ |
275 | clearScreenRows(0, 24);␊ |
276 | setCursorPosition(0, 0, 1);␊ |
277 | printf("\nusage:\n");␊ |
278 | printf("\n?rd i - display ramdisk information");␊ |
279 | printf("\n?rd m <filename> - mount ramdisk image\n?rd u - unmount ramdisk image");␊ |
280 | printf("\n?rd e - enable bt(0,0) alias\n?rd d - disable bt(0,0) alias");␊ |
281 | printf("\n\nPress any key to continue.\n");␊ |
282 | getc();␊ |
283 | setActiveDisplayPage(0);␊ |
284 | }␊ |
285 | }␊ |
286 | |