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

Archive Download this file

Revision: 2182