Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/RamDiskLoader/ramdisk.c

1/*
2 * Supplemental ramdisk functions for the multiboot ramdisk driver.
3 * Copyright 2009 Tamas Kosarszky. All rights reserved.
4 *
5 */
6
7#include "libsaio.h"
8#include "bootstruct.h"
9#include "multiboot.h"
10#include "ramdisk.h"
11
12struct multiboot_info * gRAMDiskMI = NULL;
13
14config_file_t ramdiskConfig;
15
16// gRAMDiskVolume holds the bvr for the mounted ramdisk image.
17BVRef gRAMDiskVolume = NULL;
18bool gRAMDiskBTAliased = false;
19char gRAMDiskFile[512];
20
21long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p) = NULL;
22int (*p_ramdiskReadBytes)( int biosdev, unsigned int blkno,
23 unsigned int byteoff,
24 unsigned int byteCount, void * buffer ) = NULL;
25int (*p_get_ramdisk_info)(int biosdev, struct driveInfo *dip) = NULL;
26
27int multibootRamdiskReadBytes( int biosdev, unsigned int blkno,
28 unsigned int byteoff,
29 unsigned int byteCount, void * buffer );
30int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip);
31static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p);
32
33
34// Notify OS X that a ramdisk has been setup. XNU with attach this to /dev/md0 (WARNING : md0Ramdisk MUST BE EXTERN FOR NBI COMPTATIBILITY)
35void md0Ramdisk()
36{
37RAMDiskParam ramdiskPtr;
38char filename[512];
39const char* override_filename = 0;
40int fh = -1;
41int len;
42
43if(getValueForKey(kMD0Image, &override_filename, &len,
44 DEFAULT_BOOT_CONFIG))
45{
46// Use user specified md0 file
47sprintf(filename, "%s", override_filename);
48fh = open(filename);
49
50if(fh < 0)
51{
52sprintf(filename, "bt(0,0)/Extra/%s", override_filename);
53fh = open(filename);
54
55if(fh < 0)
56{
57sprintf(filename, "rd(0,0)/Extra/%s", override_filename);
58fh = open(filename);
59
60if(fh < 0)
61{
62sprintf(filename, "/Extra/%s", override_filename);
63fh = open(filename);
64}
65}
66}
67}
68
69if(fh < 0)
70{
71sprintf(filename, "bt(0,0)/Extra/Postboot.img");
72fh = open(filename);
73
74if(fh < 0)
75{
76sprintf(filename, "rd(0,0)/Extra/Postboot.img");
77fh = open(filename);
78
79if(fh < 0)
80{
81sprintf(filename, "/Extra/Postboot.img");// Check /Extra if not in rd(0,0)
82fh = open(filename);
83}
84}
85}
86
87if (fh >= 0)
88{
89verbose("Enabling ramdisk %s\n", filename);
90
91ramdiskPtr.size = file_size(fh);
92ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size);
93
94if(ramdiskPtr.size && ramdiskPtr.base)
95{
96// Read new ramdisk image contents in kernel memory.
97if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size)
98{
99#if UNUSED
100 AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid);
101#else
102 AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size);
103#endif
104Node* node = DT__FindNode("/chosen/memory-map", false);
105if(node != NULL)
106{
107DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr);
108}
109else
110{
111verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename);
112}
113}
114else
115{
116verbose("Unable to read md0 image %s.\n", filename);
117}
118}
119else
120{
121verbose("md0 image %s is empty.\n", filename);
122}
123
124close(fh);
125
126}
127}
128
129void umountRAMDisk(void)
130{
131if (gRAMDiskMI != NULL)
132{
133// Release ramdisk BVRef and DiskBVMap.
134struct DiskBVMap *oldMap = diskResetBootVolumes(0x100);
135CacheReset();
136diskFreeMap(oldMap);
137
138// Free multiboot info and module structures.
139if ((void *)gRAMDiskMI->mi_mods_addr != NULL) free((void *)gRAMDiskMI->mi_mods_addr);
140if (gRAMDiskMI != NULL) free(gRAMDiskMI);
141
142// Reset multiboot structures.
143gRAMDiskMI = NULL;
144
145*gRAMDiskFile = '\0';
146
147// Release ramdisk driver hooks.
148p_get_ramdisk_info = NULL;
149p_ramdiskReadBytes = NULL;
150LoadExtraDrivers_p = NULL;
151
152// Reset ramdisk bvr
153gRAMDiskVolume = NULL;
154printf("\nunmounting: done");
155}
156}
157
158int mountRAMDisk(const char * param)
159{
160int fh = 0, ramDiskSize;
161int error = 0;
162
163// Get file handle for ramdisk file.
164fh = open(param);
165if (fh != -1)
166{
167printf("\nreading ramdisk image: %s\n", param);
168
169ramDiskSize = file_size(fh);
170if (ramDiskSize > 0)
171{
172// Unmount previously mounted image if exists.
173umountRAMDisk();
174
175// Read new ramdisk image contents into PREBOOT_DATA area.
176if (read(fh, (char *)PREBOOT_DATA, ramDiskSize) != ramDiskSize) error = -1;
177}
178else error = -1;
179
180close(fh);
181}
182else error = -1;
183
184if (error == 0)
185{
186// Save filename in gRAMDiskFile to display information.
187strcpy(gRAMDiskFile, param);
188
189// Set gRAMDiskMI as well for the multiboot ramdisk driver hook.
190gRAMDiskMI = malloc(sizeof(multiboot_info));
191
192struct multiboot_module * ramdisk_module = malloc(sizeof(multiboot_module));
193
194// Fill in multiboot info and module structures.
195if (gRAMDiskMI != NULL && ramdisk_module != NULL)
196{
197gRAMDiskMI->mi_mods_count = 1;
198gRAMDiskMI->mi_mods_addr = (uint32_t)ramdisk_module;
199ramdisk_module->mm_mod_start = PREBOOT_DATA;
200ramdisk_module->mm_mod_end = PREBOOT_DATA + ramDiskSize;
201
202// Set ramdisk driver hooks.
203p_get_ramdisk_info = &multiboot_get_ramdisk_info;
204p_ramdiskReadBytes = &multibootRamdiskReadBytes;
205LoadExtraDrivers_p = &multiboot_LoadExtraDrivers;
206
207int partCount; // unused
208// Save bvr of the mounted image.
209gRAMDiskVolume = diskScanBootVolumes(0x100, &partCount);
210if(gRAMDiskVolume == NULL)
211{
212umountRAMDisk();
213printf("\nRamdisk contains no partitions.\n");
214pause();
215
216 // error = -1; // ??
217
218}
219else
220{
221char dirSpec[128];
222
223// Reading ramdisk configuration.
224strcpy(dirSpec, RAMDISKCONFIG_FILENAME);
225
226if (loadConfigFile(dirSpec, &ramdiskConfig) == 0)
227{
228getBoolForKey("BTAlias", &gRAMDiskBTAliased, &ramdiskConfig);
229}
230else
231{
232verbose("\nno ramdisk config...\n");
233}
234
235printf("\nmounting: done");
236}
237}
238 else error = -1;
239
240 if (error == -1) {
241 if (ramdisk_module)
242 free(ramdisk_module);
243 else if (gRAMDiskMI)
244 free(gRAMDiskMI);
245 }
246}
247
248return error;
249}
250
251void setRAMDiskBTHook(bool mode)
252{
253gRAMDiskBTAliased = mode;
254if (mode)
255{
256printf("\nEnabled bt(0,0) alias.");
257}
258else
259{
260printf("\nDisabled bt(0,0) alias.");
261}
262}
263
264void showInfoRAMDisk(void)
265{
266int len;
267const char *val;
268
269if (gRAMDiskMI != NULL)
270{
271struct multiboot_module * ramdisk_module = (void *)gRAMDiskMI->mi_mods_addr;
272
273printf("\nfile: %s %d", gRAMDiskFile,
274ramdisk_module->mm_mod_end - ramdisk_module->mm_mod_start);
275printf("\nalias: %s", gRAMDiskBTAliased ? "enabled" : "disabled");
276
277// Display ramdisk information if available.
278if (getValueForKey("Info", &val, &len, &ramdiskConfig))
279{
280printf("\ninfo: %s", val);
281}
282else
283{
284printf("\nramdisk info not available.");
285}
286}
287else
288{
289printf("\nNo ramdisk mounted.");
290}
291}
292
293int loadPrebootRAMDisk(void)
294{
295mountRAMDisk("bt(0,0)/Extra/Preboot.dmg");
296if (gRAMDiskMI != NULL)
297{
298printf("\n");
299return 0;
300}
301else
302{
303return -1;
304}
305}
306
307void processRAMDiskCommand(char ** argPtr, const char * cmd)
308{
309char * ptr = *argPtr;
310char param[1024];
311getNextArg(&ptr, param);
312
313if (strcmp(cmd, "m") == 0)
314{
315mountRAMDisk(param);
316sleep(2);
317}
318else if (strcmp(cmd, "u") == 0)
319{
320umountRAMDisk();
321sleep(2);
322}
323else if (strcmp(cmd, "e") == 0)
324{
325setRAMDiskBTHook(true);
326sleep(2);
327}
328else if (strcmp(cmd, "d") == 0)
329{
330setRAMDiskBTHook(false);
331sleep(2);
332}
333else if (strcmp(cmd, "i") == 0)
334{
335setActiveDisplayPage(1);
336clearScreenRows(0, 24);
337setCursorPosition(0, 0, 1);
338showInfoRAMDisk();
339printf("\n\nPress any key to continue.\n");
340getc();
341setActiveDisplayPage(0);
342}
343else
344{
345setActiveDisplayPage(1);
346clearScreenRows(0, 24);
347setCursorPosition(0, 0, 1);
348printf("\nusage:\n");
349printf("\n?rd i - display ramdisk information");
350printf("\n?rd m <filename> - mount ramdisk image\n?rd u - unmount ramdisk image");
351printf("\n?rd e - enable bt(0,0) alias\n?rd d - disable bt(0,0) alias");
352printf("\n\nPress any key to continue.\n");
353getc();
354setActiveDisplayPage(0);
355}
356}
357
358///////////////////////////////////////////////////////////////////////////
359// Ramdisk multiboot support
360
361int multibootRamdiskReadBytes( int biosdev, unsigned int blkno,
362 unsigned int byteoff,
363 unsigned int byteCount, void * buffer )
364{
365 int module_count = gRAMDiskMI->mi_mods_count;
366 struct multiboot_module *modules = (void*)gRAMDiskMI->mi_mods_addr;
367 if(biosdev < 0x100)
368 return -1;
369 if(biosdev >= (0x100 + module_count))
370 return -1;
371 struct multiboot_module *module = modules + (biosdev - 0x100);
372
373 void *p_initrd = (void*)module->mm_mod_start;
374 bcopy(p_initrd + blkno*512 + byteoff, buffer, byteCount);
375 return 0;
376}
377
378int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip)
379{
380 int module_count = gRAMDiskMI->mi_mods_count;
381 struct multiboot_module *modules = (void*)gRAMDiskMI->mi_mods_addr;
382 if(biosdev < 0x100)
383 return -1;
384 if(biosdev >= (0x100 + module_count))
385 return -1;
386 struct multiboot_module *module = modules + (biosdev - 0x100);
387 dip->biosdev = biosdev;
388 dip->uses_ebios = true;// XXX aserebln uses_ebios isn't a boolean at all
389 dip->di.params.phys_sectors = (module->mm_mod_end - module->mm_mod_start + 511) / 512;
390 dip->valid = true;
391 return 0;
392}
393
394static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p)
395{
396 char extensionsSpec[1024];
397 int ramdiskUnit;
398 for(ramdiskUnit = 0; ramdiskUnit < gRAMDiskMI->mi_mods_count; ++ramdiskUnit)
399 {
400 int partCount; // unused
401 BVRef ramdiskChain = diskScanBootVolumes(0x100 + ramdiskUnit, &partCount);
402 if(ramdiskChain == NULL)
403 {
404 verbose("Ramdisk contains no partitions\n");
405 continue;
406 }
407 for(; ramdiskChain != NULL; ramdiskChain = ramdiskChain->next)
408 {
409 sprintf(extensionsSpec, "rd(%d,%d)/Extra/", ramdiskUnit, ramdiskChain->part_no);
410 struct dirstuff *extradir = opendir(extensionsSpec);
411 closedir(extradir);
412 if(extradir != NULL)
413 {
414 int ret = FileLoadDrivers_p(extensionsSpec, 0 /* this is a kext root dir, not a kext with plugins */);
415 if(ret != 0)
416 {
417 verbose("FileLoadDrivers failed on a ramdisk\n");
418 return ret;
419 }
420 }
421 }
422 }
423 return 0;
424}
425

Archive Download this file

Revision: 1913