Index: gnumach/Makefrag.am =================================================================== --- gnumach.orig/Makefrag.am 2010-06-12 03:44:45.000000000 +0200 +++ gnumach/Makefrag.am 2010-06-12 03:45:00.000000000 +0200 @@ -275,6 +275,8 @@ device/net_io.c \ device/net_io.h \ device/param.h \ + device/ramdisk.c \ + device/ramdisk.h \ device/subrs.c \ device/tty.h EXTRA_DIST += \ Index: gnumach/i386/i386at/conf.c =================================================================== --- gnumach.orig/i386/i386at/conf.c 2010-06-12 03:44:45.000000000 +0200 +++ gnumach/i386/i386at/conf.c 2010-06-12 03:45:00.000000000 +0200 @@ -29,6 +29,7 @@ #include #include +#include extern int timeopen(), timeclose(); extern vm_offset_t timemmap(); @@ -127,6 +128,8 @@ nodev, nulldev, nulldev, 0, nodev }, + RAMDISK_DEV_OPS, + #ifdef MACH_KMSG { kmsgname, kmsgopen, kmsgclose, kmsgread, nodev, kmsggetstat, nodev, nomap, Index: gnumach/kern/boot_script.c =================================================================== --- gnumach.orig/kern/boot_script.c 2010-06-12 03:44:45.000000000 +0200 +++ gnumach/kern/boot_script.c 2010-06-12 03:45:00.000000000 +0200 @@ -88,12 +88,20 @@ return boot_script_prompt_task_resume (cmd); } +/* Create an initial ramdisk */ +static int +ramdisk_create (struct cmd *cmd, int *val) +{ + return boot_script_ramdisk_create (cmd, (char **) val); +} + /* List of builtin symbols. */ static struct sym builtin_symbols[] = { { "task-create", VAL_FUNC, (int) create_task, VAL_TASK, 0 }, { "task-resume", VAL_FUNC, (int) resume_task, VAL_NONE, 1 }, { "prompt-task-resume", VAL_FUNC, (int) prompt_resume_task, VAL_NONE, 1 }, + { "ramdisk-create", VAL_FUNC, (int) ramdisk_create, VAL_STR, 0 }, }; #define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0])) Index: gnumach/kern/bootstrap.c =================================================================== --- gnumach.orig/kern/bootstrap.c 2010-06-12 03:44:44.000000000 +0200 +++ gnumach/kern/bootstrap.c 2010-06-12 03:45:00.000000000 +0200 @@ -48,6 +48,7 @@ #include #include #include +#include #if MACH_KDB #include @@ -128,7 +129,7 @@ } else { - int i, losers, maxlen; + int i, losers; /* Initialize boot script variables. We leak these send rights. */ losers = boot_script_set_variable @@ -219,23 +220,19 @@ } #endif - maxlen = 0; for (i = 0; i < boot_info.mods_count; ++i) { int err; char *line = (char*)phystokv(bmods[i].string); - int len = strlen (line) + 1; - if (len > maxlen) - maxlen = len; - printf ("\rmodule %d: %*s", i, -maxlen, line); + printf ("module %d: %s\n", i, line); err = boot_script_parse_line (&bmods[i], line); if (err) { - printf ("\n\tERROR: %s", boot_script_error_string (err)); + printf ("\tERROR: %s\n", boot_script_error_string (err)); ++losers; } } - printf ("\r%d multiboot modules %*s", i, -maxlen, ""); + printf ("%d multiboot modules\n", i); if (losers) panic ("%d of %d boot script commands could not be parsed", losers, boot_info.mods_count); @@ -776,6 +773,23 @@ } int +boot_script_ramdisk_create (struct cmd *cmd, char **name) +{ + struct multiboot_module *mod = cmd->hook; + vm_size_t size = mod->mod_end - mod->mod_start; + kern_return_t rc; + int no; + + rc = ramdisk_create (size, (void *) phystokv (mod->mod_start), &no); + if (rc != KERN_SUCCESS) + return BOOT_SCRIPT_MACH_ERROR; + + *name = boot_script_malloc (RAMDISK_NAMESZ); + sprintf(*name, RAMDISK_NAME "%d", no); + return 0; +} + +int boot_script_task_create (struct cmd *cmd) { kern_return_t rc = task_create(TASK_NULL, FALSE, &cmd->task); Index: gnumach/device/ramdisk.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gnumach/device/ramdisk.c 2010-06-12 05:02:54.000000000 +0200 @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ramdisk { + void *data; + vm_size_t size; +} ramdisk[RAMDISK_MAX]; + +static int ramdisk_num = 0; + +/* Initial ramdisks are created from the boot scripts */ +int ramdisk_create(vm_size_t size, const void *initdata, int *out_no) +{ + struct ramdisk *rd = &ramdisk[ramdisk_num]; + int err; + + if(ramdisk_num >= RAMDISK_MAX) + return -1; + + /* allocate the memory */ + rd->size = round_page(size); + err = kmem_alloc(kernel_map, (vm_offset_t *) &rd->data, rd->size); + if(err != KERN_SUCCESS) + return err; + + /* initialize */ + if(initdata) + memcpy(rd->data, initdata, rd->size); + else + memset(rd->data, 0, rd->size); + + /* report */ + if(out_no) *out_no = ramdisk_num; + printf("%s%d: %lu bytes @%p\n", RAMDISK_NAME, ramdisk_num, + (unsigned long) rd->size, rd->data); + + ramdisk_num++; + return KERN_SUCCESS; +} + +/* On d_open() we just check whether the ramdisk exists */ +int ramdisk_open(int dev, int mode, io_req_t ior) +{ + return (dev < ramdisk_num) ? D_SUCCESS : D_NO_SUCH_DEVICE; +} + +/* d_getstat() is used to query the device characteristics */ +int ramdisk_getstat(int dev, dev_flavor_t flavor, dev_status_t status, + mach_msg_type_number_t *status_count) +{ + switch(flavor) { + case DEV_GET_SIZE: + status[DEV_GET_SIZE_DEVICE_SIZE] = ramdisk[dev].size; + status[DEV_GET_SIZE_RECORD_SIZE] = RAMDISK_BLOCKSZ; + *status_count = DEV_GET_SIZE_COUNT; + return D_SUCCESS; + + case DEV_GET_RECORDS: + status[DEV_GET_RECORDS_DEVICE_RECORDS] + = ramdisk[dev].size / RAMDISK_BLOCKSZ; + status[DEV_GET_RECORDS_RECORD_SIZE] = RAMDISK_BLOCKSZ; + *status_count = DEV_GET_RECORDS_COUNT; + return D_SUCCESS; + } + return D_INVALID_OPERATION; +} + +/* TODO: implement freeramdisk with setstat() ? */ + +/* Check the given io request and compute a pointer to the ramdisk data and the + * amount to be handled. */ +static int ramdisk_ioreq(int dev, io_req_t ior, void **data, int *amt) +{ + vm_offset_t ofs = ior->io_recnum * RAMDISK_BLOCKSZ; + if(ofs >= ramdisk[dev].size) + return D_INVALID_RECNUM; + + *data = (char*) ramdisk[dev].data + ofs; + *amt = ior->io_count; + if(ofs + *amt > ramdisk[dev].size) + *amt = ramdisk[dev].size - ofs; + + return KERN_SUCCESS; +} + +/* Copy data from a vm_map_copy by mapping it temporarily. */ +static int mem_map_cpy(void *dst, vm_map_copy_t src, int amt) +{ + vm_offset_t srcaddr; + int err; + + err = vm_map_copyout(device_io_map, &srcaddr, src); + if (err != KERN_SUCCESS) + return err; + + memcpy(dst, (void *) srcaddr, amt); + vm_deallocate(device_io_map, srcaddr, amt); + return KERN_SUCCESS; +} + +int ramdisk_read(int dev, io_req_t ior) +{ + void *data; + int amt, err; + + err = ramdisk_ioreq(dev, ior, &data, &amt); + if(err != KERN_SUCCESS) + return err; + + err = device_read_alloc (ior, ior->io_count); + if (err != KERN_SUCCESS) + return err; + + memcpy(ior->io_data, data, amt); + ior->io_residual = ior->io_count - amt; + + return D_SUCCESS; +} + +int ramdisk_write(int dev, io_req_t ior) +{ + void *data; + int amt, err; + + err = ramdisk_ioreq(dev, ior, &data, &amt); + if(err != KERN_SUCCESS) + return err; + + if (!(ior->io_op & IO_INBAND)) { + /* Out-of-band data is transmitted as a vm_map_copy */ + err = mem_map_cpy(data, (vm_map_copy_t) ior->io_data, amt); + if(err != KERN_SUCCESS) + return err; + } else { + /* In-band data can be accessed directly */ + memcpy(data, ior->io_data, amt); + } + + ior->io_residual = ior->io_count - amt; + return D_SUCCESS; +} + +vm_offset_t ramdisk_mmap(int dev, vm_offset_t off, vm_prot_t prot) +{ + if(dev >= ramdisk_num) + return -1; + if(off >= ramdisk[dev].size) + return -1; + + return pmap_phys_to_frame(kvtophys((vm_offset_t) ramdisk[dev].data + off)); +} + Index: gnumach/device/ramdisk.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gnumach/device/ramdisk.h 2010-06-12 03:45:00.000000000 +0200 @@ -0,0 +1,47 @@ +#ifndef _KERN_RAMDISK_H_ +#define _KERN_RAMDISK_H_ + +#include +#include +#include + +/* Maximum number of ramdisk devices */ +#define RAMDISK_MAX 4 + +/* The block size used (userspace requires 512) */ +#define RAMDISK_BLOCKSZ 512 + +/* Name associated to the ramdisk major */ +#define RAMDISK_NAME "rd" +#define RAMDISK_NAMESZ (sizeof RAMDISK_NAME + sizeof (int) * 3 + 1) + +/* Create a new ramdisk of the given size. On success, if out_no and/or out_ptr + * are not NULL, the device number and pointer to the ramdisk's data are stored + * there. Returns D_SUCCESS or D_NO_MEMORY. */ +int ramdisk_create(vm_size_t size, const void *initdata, int *out_no); + +/* Device operations */ +int ramdisk_open(int, int, io_req_t); +int ramdisk_getstat(int, dev_flavor_t, dev_status_t, mach_msg_type_number_t *); +int ramdisk_read(int, io_req_t); +int ramdisk_write(int, io_req_t); +vm_offset_t ramdisk_mmap(int, vm_offset_t, vm_prot_t); + +/* dev_ops initializer to be used from /conf.c */ +#define RAMDISK_DEV_OPS { \ + .d_name = RAMDISK_NAME, \ + .d_open = ramdisk_open, \ + .d_close = nulldev, \ + .d_read = ramdisk_read, \ + .d_write = ramdisk_write, \ + .d_getstat = ramdisk_getstat, \ + .d_setstat = nodev, \ + .d_mmap = ramdisk_mmap, \ + .d_async_in = nodev, \ + .d_reset = nulldev, \ + .d_port_death = nulldev, \ + .d_subdev = 0, \ + .d_dev_info = nodev, \ + } + +#endif