Skip to content

Commit 589b1dd

Browse files
committed
drivers: add ramdisk storage driver
1 parent 34904cc commit 589b1dd

9 files changed

Lines changed: 213 additions & 26 deletions

File tree

platform/pc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ SRCS-kernel.elf= \
2222
$(SRCDIR)/drivers/gve.c \
2323
$(SRCDIR)/drivers/nvme.c \
2424
$(SRCDIR)/drivers/netconsole.c \
25+
$(SRCDIR)/drivers/ramdisk.c \
2526
$(SRCDIR)/drivers/vga.c \
2627
$(SRCDIR)/gdb/gdbstub.c \
2728
$(SRCDIR)/gdb/gdbtcp.c \

platform/pc/service.c

Lines changed: 129 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
#include <pci.h>
1919
#include <xen_platform.h>
2020
#include <virtio/virtio.h>
21+
#include <drivers/ramdisk.h>
2122
#include <vmware/vmware.h>
2223
#include "serial.h"
2324

2425
#define BOOT_PARAM_OFFSET_E820_ENTRIES 0x01E8
2526
#define BOOT_PARAM_OFFSET_BOOT_FLAG 0x01FE
2627
#define BOOT_PARAM_OFFSET_HEADER 0x0202
28+
#define BOOT_PARAM_OFFSET_RAMDISK_IMAGE 0x0218
29+
#define BOOT_PARAM_OFFSET_RAMDISK_SIZE 0x021C
2730
#define BOOT_PARAM_OFFSET_CMD_LINE_PTR 0x0228
2831
#define BOOT_PARAM_OFFSET_CMDLINE_SIZE 0x0238
2932
#define BOOT_PARAM_OFFSET_E820_TABLE 0x02D0
@@ -64,8 +67,17 @@ typedef struct hvm_memmap_entry {
6467
u32 reserved;
6568
} *hvm_memmap_entry;
6669

70+
typedef struct hvm_modlist_entry {
71+
u64 paddr;
72+
u64 size;
73+
u64 cmdline_paddr;
74+
u64 reserved;
75+
} *hvm_modlist_entry;
76+
6777
extern u8 START, END;
6878

79+
boolean cmdline_verbose_logging = false;
80+
6981
range kern_get_elf(void)
7082
{
7183
for_regions(e) {
@@ -75,6 +87,15 @@ range kern_get_elf(void)
7587
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
7688
}
7789

90+
range kern_get_ramdisk(void)
91+
{
92+
for_regions(e) {
93+
if (e->type == REGION_RAMDISK)
94+
return irangel(e->base, e->length);
95+
}
96+
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
97+
}
98+
7899
BSS_RO_AFTER_INIT static boolean have_rdseed;
79100
BSS_RO_AFTER_INIT static boolean have_rdrand;
80101

@@ -292,20 +313,21 @@ void init_physical_heap(void)
292313
}
293314

294315
boolean found = false;
295-
early_init_debug("physical memory:");
316+
if (cmdline_verbose_logging)
317+
early_debug("Physical memory: \n");
296318
for_regions(e) {
297319
if (e->type == REGION_PHYSICAL) {
298320
u64 base = e->base;
299321
u64 length = e->length;
300322
if (length == 0)
301323
continue;
302-
#ifdef INIT_DEBUG
303-
early_debug("INIT: [");
304-
early_debug_u64(base);
305-
early_debug(", ");
306-
early_debug_u64(base + length);
307-
early_debug(")\n");
308-
#endif
324+
if (cmdline_verbose_logging) {
325+
early_debug("\t[");
326+
early_debug_u64(base);
327+
early_debug(", ");
328+
early_debug_u64(base + length);
329+
early_debug(")\n");
330+
}
309331
if (!pageheap_add_range(base, length))
310332
halt(" - id_heap_add_range failed\n");
311333
found = true;
@@ -319,19 +341,59 @@ void init_physical_heap(void)
319341
static void setup_initmap(void)
320342
{
321343
u64 kernel_size = u64_from_pointer(&END) - KERNEL_BASE_PHYS;
344+
create_region(KERNEL_BASE_PHYS, kernel_size, REGION_KERN_LOAD);
345+
322346
region page_region = 0;
323347
for_regions(r) {
324-
if ((r->type == REGION_PHYSICAL) && (r->base <= KERNEL_BASE_PHYS) &&
325-
(r->base + r->length > KERNEL_BASE_PHYS)) {
326-
/* This is the memory region where the kernel has been loaded: adjust the region
327-
* boundaries so that the memory occupied by the kernel code does not appear as free
328-
* memory, and possibly and make a new memory region. */
329-
if (r->base < KERNEL_BASE_PHYS)
330-
create_region(r->base, KERNEL_BASE_PHYS - r->base, r->type);
331-
region_resize(r, r->base - pad(KERNEL_BASE_PHYS + kernel_size, PAGESIZE));
332-
333-
page_region = r;
334-
break;
348+
if (r->type == REGION_PHYSICAL) {
349+
for_regions(s) {
350+
if (s->type != REGION_PHYSICAL &&
351+
s->length != 0 &&
352+
r->base <= s->base &&
353+
r->base + r->length > s->base) {
354+
u64 inner_start = s->base;
355+
u64 inner_end = s->base + s->length;
356+
357+
if (inner_end > r->base + r->length) {
358+
inner_end = r->base + r->length;
359+
}
360+
if (cmdline_verbose_logging) {
361+
early_debug("Reserving region: [");
362+
early_debug_u64(r->base);
363+
early_debug(" - ");
364+
early_debug_u64(r->base + r->length);
365+
early_debug("] (physmem), [");
366+
early_debug_u64(inner_start);
367+
early_debug(" - ");
368+
early_debug_u64(inner_end);
369+
early_debug("] (");
370+
early_debug_u64(s->type);
371+
early_debug(")\n");
372+
}
373+
if (r->base < inner_start) {
374+
create_region(r->base, inner_start - r->base, r->type);
375+
if (cmdline_verbose_logging) {
376+
early_debug("\tcreate: ");
377+
early_debug_u64(r->base);
378+
early_debug(" - ");
379+
early_debug_u64(inner_start);
380+
early_debug("\n");
381+
}
382+
}
383+
region_resize(r, r->base - pad(inner_end, PAGESIZE));
384+
if (cmdline_verbose_logging) {
385+
early_debug("\tshrink: ");
386+
early_debug_u64(r->base);
387+
early_debug(" - ");
388+
early_debug_u64(r->base + r->length);
389+
early_debug("\n");
390+
}
391+
if (s->type == REGION_KERN_LOAD) {
392+
assert(!page_region);
393+
page_region = r;
394+
}
395+
}
396+
}
335397
}
336398
}
337399
assert(page_region);
@@ -366,11 +428,13 @@ static void setup_initmap(void)
366428
}
367429

368430
// init linker set
369-
void init_service(u64 rdi, u64 rsi)
431+
void init_service(u64 rdi, u64 rsi, hvm_start_info start_info)
370432
{
371433
u8 *params = pointer_from_u64(rsi);
372434
const char *cmdline = 0;
373435
u32 cmdline_size;
436+
void *ramdisk = 0;
437+
u32 ramdisk_size;
374438

375439
if (params && (*(u16 *)(params + BOOT_PARAM_OFFSET_BOOT_FLAG) == 0xAA55) &&
376440
(*(u32 *)(params + BOOT_PARAM_OFFSET_HEADER) == 0x53726448)) {
@@ -389,9 +453,51 @@ void init_service(u64 rdi, u64 rsi)
389453
BOOT_PARAM_OFFSET_CMD_LINE_PTR)));
390454
cmdline_size = *((u32 *)(params + BOOT_PARAM_OFFSET_CMDLINE_SIZE));
391455

392-
setup_initmap();
456+
ramdisk = pointer_from_u64((u64)*((u32 *)(params +
457+
BOOT_PARAM_OFFSET_RAMDISK_IMAGE)));
458+
ramdisk_size = *((u32 *)(params + BOOT_PARAM_OFFSET_RAMDISK_SIZE));
459+
} else if (start_info)
460+
{
461+
cmdline = pointer_from_u64(start_info->cmdline_paddr);
462+
cmdline_size = 0;
463+
const char *cmdline_p = cmdline;
464+
while (*cmdline_p)
465+
{
466+
cmdline_size++;
467+
cmdline_p++;
468+
}
469+
470+
if (start_info->nr_modules)
471+
{
472+
hvm_modlist_entry ramdisk_entry = pointer_from_u64(start_info->modlist_paddr);
473+
ramdisk = pointer_from_u64(ramdisk_entry->paddr);
474+
ramdisk_size = ramdisk_entry->size;
475+
}
476+
}
477+
478+
if (cmdline) {
479+
create_region(u64_from_pointer(cmdline), cmdline_size, REGION_CMDLINE);
480+
sstring input = sstring_from_cstring(cmdline, cmdline_size);
481+
sstring token, rest;
482+
sstring delim = ss(" ");
483+
token = runtime_strtok_r(&input, delim, &rest);
484+
while (!sstring_is_null(token)) {
485+
if(runtime_strcmp(token, ss("verbose")) == 0) {
486+
cmdline_verbose_logging = true;
487+
}
488+
token = runtime_strtok_r(0, delim, &rest);
489+
}
393490
}
394491

492+
if (ramdisk)
493+
create_region(u64_from_pointer(ramdisk), ramdisk_size, REGION_RAMDISK);
494+
495+
#ifdef INIT_DEBUG
496+
cmdline_verbose_logging = true;
497+
#endif
498+
499+
setup_initmap();
500+
395501
serial_init();
396502
early_init_debug("init_service");
397503

@@ -402,8 +508,6 @@ void init_service(u64 rdi, u64 rsi)
402508
init_hwrand();
403509
kaslr();
404510
init_kernel_heaps();
405-
if (cmdline)
406-
create_region(u64_from_pointer(cmdline), cmdline_size, REGION_CMDLINE);
407511
u64 stack_size = 32*PAGESIZE;
408512
u64 stack_location = allocate_u64((heap)heap_page_backed(get_kernel_heaps()), stack_size);
409513
stack_location += stack_size - STACK_ALIGNMENT;
@@ -421,8 +525,7 @@ void pvh_start(hvm_start_info start_info)
421525
if (mem_table[i].type == HVM_MEMMAP_TYPE_RAM)
422526
create_region(mem_table[i].addr, mem_table[i].size, REGION_PHYSICAL);
423527
}
424-
setup_initmap();
425-
init_service(0, 0);
528+
init_service(0, 0, start_info);
426529
}
427530

428531
RO_AFTER_INIT static struct console_driver serial_console_driver = {
@@ -499,6 +602,7 @@ void detect_devices(kernel_heaps kh, storage_attach sa)
499602
init_pvscsi(kh, sa);
500603
init_nvme(kh, sa);
501604
init_ata_pci(kh, sa);
605+
init_ramdisk(kh, sa);
502606

503607
init_virtio_9p(kh);
504608
init_virtio_socket(kh);

platform/riscv-virt/service.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ range kern_get_elf(void)
6363
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
6464
}
6565

66+
range kern_get_ramdisk(void)
67+
{
68+
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
69+
}
70+
6671
void reclaim_regions(void)
6772
{
6873
/* mmu init complete; unmap temporary identity map */

platform/virt/service.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@ range kern_get_elf(void)
194194
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
195195
}
196196

197+
range kern_get_ramdisk(void)
198+
{
199+
return irange(INVALID_PHYSICAL, INVALID_PHYSICAL);
200+
}
201+
197202
void reclaim_regions(void)
198203
{
199204
}

src/drivers/ramdisk.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <kernel.h>
2+
#include <storage.h>
3+
4+
#include "ramdisk.h"
5+
6+
typedef struct storage *storage;
7+
8+
declare_closure_struct(2, 3, void, ramdisk_io,
9+
storage, st, boolean, write,
10+
void *buf, range blocks, status_handler sh);
11+
12+
typedef struct storage
13+
{
14+
closure_struct(storage_simple_req_handler, req_handler);
15+
closure_struct(ramdisk_io, read);
16+
closure_struct(ramdisk_io, write);
17+
void *ramdisk;
18+
u64 ramdisk_size;
19+
} *storage;
20+
21+
define_closure_function(2, 3, void, ramdisk_io,
22+
storage, st, boolean, write,
23+
void *buf, range blocks, status_handler sh)
24+
{
25+
storage st = bound(st);
26+
boolean write = bound(write);
27+
28+
if (write)
29+
{
30+
apply(sh, timm("result", "read-only device"));
31+
return;
32+
}
33+
34+
u64 start_byte_offset = blocks.start * SECTOR_SIZE;
35+
u64 end_byte_offset = blocks.end * SECTOR_SIZE;
36+
if (start_byte_offset > end_byte_offset || end_byte_offset > st->ramdisk_size)
37+
{
38+
apply(sh, timm("result", "read out of bounds"));
39+
return;
40+
}
41+
42+
runtime_memcpy(buf, st->ramdisk + start_byte_offset, end_byte_offset - start_byte_offset);
43+
apply(sh, STATUS_OK);
44+
}
45+
46+
void init_ramdisk(kernel_heaps kh, storage_attach a)
47+
{
48+
range ramdisk_phys = kern_get_ramdisk();
49+
if (ramdisk_phys.start == INVALID_PHYSICAL)
50+
{
51+
msg_print("RAMDISK: not detected");
52+
return;
53+
}
54+
u64 ramdisk_size = range_span(ramdisk_phys);
55+
u64 v = allocate_u64((heap)heap_virtual_huge(kh), ramdisk_size);
56+
map(v, ramdisk_phys.start, ramdisk_size, pageflags_memory());
57+
58+
heap h = heap_locked(kh);
59+
storage st = allocate(h, sizeof(struct storage));
60+
st->ramdisk = pointer_from_u64(v);
61+
st->ramdisk_size = ramdisk_size;
62+
apply(a,
63+
storage_init_req_handler(&st->req_handler,
64+
init_closure(&st->read, ramdisk_io, st, false),
65+
init_closure(&st->write, ramdisk_io, st, true)),
66+
ramdisk_size, -1);
67+
msg_print("RAMDISK: %u bytes at %p", st->ramdisk_size, st->ramdisk);
68+
}

src/drivers/ramdisk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void init_ramdisk(kernel_heaps kh, storage_attach a);

src/kernel/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ void init_platform_devices(kernel_heaps kh);
602602
void init_cpuinfo_machine(cpuinfo ci, heap backed);
603603
void kernel_runtime_init(kernel_heaps kh);
604604
range kern_get_elf(void);
605+
range kern_get_ramdisk(void);
605606
void reclaim_regions(void);
606607

607608
extern u64 kernel_phys_offset;

src/kernel/region.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ typedef struct region *region;
1919
#define REGION_RECLAIM 14 /* areas to be unmapped and reclaimed in stage3 (only stage2 stack presently) */
2020
#define REGION_SMBIOS 15 /* SMBIOS entry point */
2121
#define REGION_RSDP 16 /* location of the ACPI RSDP */
22-
22+
#define REGION_RAMDISK 17 /* kernel ramdisk */
23+
#define REGION_KERN_LOAD 18 /* kernel load region */
2324

2425
static inline region create_region(u64 base, u64 length, int type)
2526
{

src/x86_64/crt0.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ write_xmsr:
396396
.end:
397397

398398
_start:
399+
xor edx, edx
399400
call init_service
400401
hlt
401402
.end:

0 commit comments

Comments
 (0)