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