summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Zammit <damien@zamaudio.com>2019-11-12 21:08:26 +1100
committerDamien Zammit <damien@zamaudio.com>2019-11-13 18:32:03 +1100
commitccbe784335203a210021ccac549035f58d447296 (patch)
treeaeeeb449619cf045a224e9f34bdf7278f98d05da
parent955d33b3189d31dcdc86ea33a0def24f3e781340 (diff)
-rw-r--r--Makefrag.am2
-rw-r--r--configure.ac1
-rw-r--r--device/ramdisk.c160
-rw-r--r--device/ramdisk.h47
-rw-r--r--i386/i386at/conf.c3
-rw-r--r--i386/i386at/kd.c4
-rw-r--r--i386/include/mach/i386/fp_reg.h2
-rw-r--r--kern/boot_script.c8
-rw-r--r--kern/bootstrap.c18
-rw-r--r--version.c.in2
-rw-r--r--vm/vm_map.c3
11 files changed, 248 insertions, 2 deletions
diff --git a/Makefrag.am b/Makefrag.am
index fee77894..f01707fe 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -319,6 +319,8 @@ libkernel_a_SOURCES += \
device/net_io.c \
device/net_io.h \
device/param.h \
+ device/ramdisk.c \
+ device/ramdisk.h \
device/subrs.c \
device/subrs.h \
device/tty.h
diff --git a/configure.ac b/configure.ac
index d4daa932..815f5818 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,6 +19,7 @@ AC_PREREQ([2.57])
m4_include([version.m4])
AC_INIT([AC_PACKAGE_NAME], [AC_PACKAGE_VERSION], [AC_PACKAGE_BUGREPORT],
[AC_PACKAGE_TARNAME])
+AC_SUBST([PACKAGE_VERSION_SUFFIX])
AC_CONFIG_SRCDIR([kern/ipc_kobject.c])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/device/ramdisk.c b/device/ramdisk.c
new file mode 100644
index 00000000..daf70436
--- /dev/null
+++ b/device/ramdisk.c
@@ -0,0 +1,160 @@
+#include <mach/vm_param.h>
+#include <machine/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_user.h>
+#include <device/device_types.h>
+#include <device/ds_routines.h>
+#include <device/conf.h>
+#include <device/ramdisk.h>
+#include <kern/printf.h>
+#include <string.h>
+
+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(dev_t 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(dev_t 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(dev_t 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(dev_t 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(dev_t 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));
+}
+
diff --git a/device/ramdisk.h b/device/ramdisk.h
new file mode 100644
index 00000000..3a232460
--- /dev/null
+++ b/device/ramdisk.h
@@ -0,0 +1,47 @@
+#ifndef _KERN_RAMDISK_H_
+#define _KERN_RAMDISK_H_
+
+#include <vm/pmap.h>
+#include <device/io_req.h>
+#include <device/conf.h>
+
+/* 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(dev_t, int, io_req_t);
+int ramdisk_getstat(dev_t, dev_flavor_t, dev_status_t, mach_msg_type_number_t *);
+int ramdisk_read(dev_t, io_req_t);
+int ramdisk_write(dev_t, io_req_t);
+vm_offset_t ramdisk_mmap(dev_t, vm_offset_t, vm_prot_t);
+
+/* dev_ops initializer to be used from <machine>/conf.c */
+#define RAMDISK_DEV_OPS { \
+ .d_name = RAMDISK_NAME, \
+ .d_open = ramdisk_open, \
+ .d_close = nulldev_close, \
+ .d_read = ramdisk_read, \
+ .d_write = ramdisk_write, \
+ .d_getstat = ramdisk_getstat, \
+ .d_setstat = nulldev_setstat, \
+ .d_mmap = ramdisk_mmap, \
+ .d_async_in = nodev, \
+ .d_reset = nulldev, \
+ .d_port_death = nulldev_portdeath, \
+ .d_subdev = 0, \
+ .d_dev_info = nodev, \
+ }
+
+#endif
diff --git a/i386/i386at/conf.c b/i386/i386at/conf.c
index fe7c7c09..7b82ff47 100644
--- a/i386/i386at/conf.c
+++ b/i386/i386at/conf.c
@@ -31,6 +31,7 @@
#include <device/conf.h>
#include <kern/mach_clock.h>
#include <i386at/model_dep.h>
+#include <device/ramdisk.h>
#define timename "time"
@@ -135,6 +136,8 @@ struct dev_ops dev_name_list[] =
nodev },
#endif /* MACH_HYP */
+ RAMDISK_DEV_OPS,
+
#ifdef MACH_KMSG
{ kmsgname, kmsgopen, kmsgclose, kmsgread,
nulldev_write, kmsggetstat, nulldev_setstat, nomap,
diff --git a/i386/i386at/kd.c b/i386/i386at/kd.c
index 8e9222a0..c448adab 100644
--- a/i386/i386at/kd.c
+++ b/i386/i386at/kd.c
@@ -1733,6 +1733,10 @@ kd_parserest(u_char *cp)
kd_erase(number[0]);
esc_spt = esc_seq;
break;
+ case 'n':
+ /* Ignore status/cursor report request */
+ esc_spt = esc_seq;
+ break;
case '\0':
break; /* not enough yet */
default:
diff --git a/i386/include/mach/i386/fp_reg.h b/i386/include/mach/i386/fp_reg.h
index 56730555..f4906238 100644
--- a/i386/include/mach/i386/fp_reg.h
+++ b/i386/include/mach/i386/fp_reg.h
@@ -117,6 +117,7 @@ struct i386_xfp_save {
#define FPS_C3 0x4000 /* condition code bit 3 */
#define FPS_BUSY 0x8000 /* FPU busy */
+#ifdef MACH_KERNEL
/*
* Kind of floating-point support provided by kernel.
*/
@@ -125,5 +126,6 @@ struct i386_xfp_save {
#define FP_287 2 /* 80287 */
#define FP_387 3 /* 80387 or 80486 */
#define FP_387X 4 /* FXSAVE/RSTOR-capable */
+#endif
#endif /* _MACH_I386_FP_REG_H_ */
diff --git a/kern/boot_script.c b/kern/boot_script.c
index b2ae901c..503a18de 100644
--- a/kern/boot_script.c
+++ b/kern/boot_script.c
@@ -88,12 +88,20 @@ prompt_resume_task (struct cmd *cmd, const long *val)
return boot_script_prompt_task_resume (cmd);
}
+/* Create an initial ramdisk */
+static int
+ramdisk_create (struct cmd *cmd, long *val)
+{
+ return boot_script_ramdisk_create (cmd, (char **) val);
+}
+
/* List of builtin symbols. */
static struct sym builtin_symbols[] =
{
{ "task-create", VAL_FUNC, (long) create_task, VAL_TASK, 0 },
{ "task-resume", VAL_FUNC, (long) resume_task, VAL_NONE, 1 },
{ "prompt-task-resume", VAL_FUNC, (long) prompt_resume_task, VAL_NONE, 1 },
+ { "ramdisk-create", VAL_FUNC, (long) ramdisk_create, VAL_STR, 0 },
};
#define NUM_BUILTIN (sizeof (builtin_symbols) / sizeof (builtin_symbols[0]))
diff --git a/kern/bootstrap.c b/kern/bootstrap.c
index 8b88d17d..d0afa1ef 100644
--- a/kern/bootstrap.c
+++ b/kern/bootstrap.c
@@ -51,6 +51,7 @@
#include <vm/vm_user.h>
#include <vm/pmap.h>
#include <device/device_port.h>
+#include <device/ramdisk.h>
#if MACH_KDB
#include <machine/db_machdep.h>
@@ -817,6 +818,23 @@ boot_script_free (void *ptr, unsigned int size)
}
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_kernel(TASK_NULL, FALSE, &cmd->task);
diff --git a/version.c.in b/version.c.in
index d894d7fc..2c57314f 100644
--- a/version.c.in
+++ b/version.c.in
@@ -1,2 +1,2 @@
/* @configure_input@ */
-const char version[] = "@PACKAGE_NAME@ @PACKAGE_VERSION@";
+const char version[] = "@PACKAGE_NAME@ @PACKAGE_VERSION@@PACKAGE_VERSION_SUFFIX@";
diff --git a/vm/vm_map.c b/vm/vm_map.c
index ffc8934b..4a133eb3 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -1035,7 +1035,8 @@ kern_return_t vm_map_enter(
* extend from below.]
*/
- if ((object == VM_OBJECT_NULL) &&
+ if (0 &&
+ (object == VM_OBJECT_NULL) &&
(entry != vm_map_to_entry(map)) &&
(entry->vme_end == start) &&
(!entry->is_shared) &&