Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
This commit is contained in:
commit
d0f7acf9eb
275 changed files with 51417 additions and 0 deletions
92
kernel/dev/ramdisk.c
Normal file
92
kernel/dev/ramdisk.c
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// Memory-backed block device.
|
||||
//
|
||||
// Serves an entire SCHFS image out of RAM, so the system can boot and run a
|
||||
// shell with the physical disk untouched. That is what makes destructive work
|
||||
// on the real disk survivable: reformatting, running mkfs, or bringing up a new
|
||||
// on-disk format cannot take away the root you are running from. It is also the
|
||||
// first piece of the installer -- an install environment is exactly "a root in
|
||||
// RAM plus a disk you are allowed to destroy".
|
||||
//
|
||||
// The image is linked into the kernel as a binary blob (see the ramdisk_obj
|
||||
// rule in the Makefile) and is served in place: the blob lives in writable
|
||||
// kernel memory, so writes to the ramdisk simply modify it. They are lost on
|
||||
// reboot, which is the expected behaviour for this kind of root.
|
||||
//
|
||||
// Enabled by building with RAMROOT=1. Without it this file still compiles, the
|
||||
// device reports zero size, and the kernel boots from the IDE disk as before.
|
||||
|
||||
#include "types.h"
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "memlayout.h"
|
||||
#include "mmu.h"
|
||||
#include "spinlock.h"
|
||||
#include "sleeplock.h"
|
||||
#include "fs.h"
|
||||
#include "buf.h"
|
||||
|
||||
#ifdef RAMDISK_ROOT
|
||||
// Supplied by `ld -r -b binary` over build/fs-ram.img, renamed by objcopy.
|
||||
extern uchar _binary_ramdisk_start[];
|
||||
extern uchar _binary_ramdisk_size[];
|
||||
#endif
|
||||
|
||||
static uchar *rd_base;
|
||||
static uint64 rd_size; // bytes
|
||||
static uint rd_blocks; // rd_size / BSIZE
|
||||
|
||||
void
|
||||
ramdiskinit(void)
|
||||
{
|
||||
#ifdef RAMDISK_ROOT
|
||||
rd_base = _binary_ramdisk_start;
|
||||
rd_size = (uint64)_binary_ramdisk_size;
|
||||
rd_blocks = (uint)(rd_size / BSIZE);
|
||||
|
||||
if(rd_blocks == 0)
|
||||
panic("ramdiskinit: embedded image is empty");
|
||||
|
||||
// A truncated image is worth catching here rather than as a confusing
|
||||
// "invalid file system" panic later: the superblock lives in block 1.
|
||||
if(rd_blocks < 2)
|
||||
panic("ramdiskinit: embedded image smaller than a superblock");
|
||||
|
||||
cprintf("ramdisk: %u blocks (%u KB) at %p\n",
|
||||
rd_blocks, (uint)(rd_size / 1024), rd_base);
|
||||
#else
|
||||
rd_base = 0;
|
||||
rd_size = 0;
|
||||
rd_blocks = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ramdisk_present(void)
|
||||
{
|
||||
return rd_blocks != 0;
|
||||
}
|
||||
|
||||
// Sync buf with the in-memory image. Mirrors iderw()'s contract: on a read,
|
||||
// fill b->data and set B_VALID; on a write, copy out and clear B_DIRTY.
|
||||
void
|
||||
ramdiskrw(struct buf *b)
|
||||
{
|
||||
if(!holdingsleep(&b->lock))
|
||||
panic("ramdiskrw: buf not locked");
|
||||
if((b->flags & (B_VALID|B_DIRTY)) == B_VALID)
|
||||
panic("ramdiskrw: nothing to do");
|
||||
if(rd_base == 0)
|
||||
panic("ramdiskrw: no ramdisk");
|
||||
if(b->blockno >= rd_blocks)
|
||||
panic("ramdiskrw: block out of range");
|
||||
|
||||
uchar *p = rd_base + (uint64)b->blockno * BSIZE;
|
||||
|
||||
if(b->flags & B_DIRTY){
|
||||
memmove(p, b->data, BSIZE);
|
||||
b->flags &= ~B_DIRTY;
|
||||
} else {
|
||||
memmove(b->data, p, BSIZE);
|
||||
}
|
||||
b->flags |= B_VALID;
|
||||
}
|
||||
Loading…
Reference in a new issue