From a3855adbde97f3bb71e2d5f153be7304ac700a89 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 16 Aug 2009 21:59:40 -0400 Subject: [PATCH] Add support for using floppy images in CBFS. Add new "ramdisk" type for disk accesses. Extract out high-mem finding code from pmm into find_high_area(). Fix bug in GDB_BASE and GDT_LIMIT macros (wrong bit shifts). --- Makefile | 2 +- src/block.c | 6 ++- src/config.h | 2 + src/coreboot.c | 2 +- src/disk.h | 7 ++++ src/floppy.c | 23 +++++++++--- src/memmap.c | 17 +++++++++ src/memmap.h | 1 + src/pmm.c | 20 +++------- src/post.c | 1 + src/ramdisk.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 10 ++--- 12 files changed, 161 insertions(+), 29 deletions(-) create mode 100644 src/ramdisk.c diff --git a/Makefile b/Makefile index 2b8d0d2..d697fca 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ OUT=out/ # Source files SRCBOTH=output.c util.c block.c floppy.c ata.c misc.c mouse.c kbd.c pci.c \ serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \ - pnpbios.c pirtable.c vgahooks.c pmm.c + pnpbios.c pirtable.c vgahooks.c pmm.c ramdisk.c SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \ diff --git a/src/block.c b/src/block.c index 3345db7..aa341a2 100644 --- a/src/block.c +++ b/src/block.c @@ -235,12 +235,14 @@ process_op(struct disk_op_s *op) { u8 type = GET_GLOBAL(Drives.drives[op->driveid].type); switch (type) { + case DTYPE_FLOPPY: + return process_floppy_op(op); case DTYPE_ATA: return process_ata_op(op); case DTYPE_ATAPI: return process_atapi_op(op); - case DTYPE_FLOPPY: - return process_floppy_op(op); + case DTYPE_RAMDISK: + return process_ramdisk_op(op); default: op->count = 0; return DISK_RET_EPARAM; diff --git a/src/config.h b/src/config.h index 72c7d71..494fe8d 100644 --- a/src/config.h +++ b/src/config.h @@ -68,6 +68,8 @@ #define CONFIG_PCI_ROOT2 0x00 // Support searching coreboot flash format. #define CONFIG_COREBOOT_FLASH 0 +// Support floppy images in the coreboot flash. +#define CONFIG_FLASH_FLOPPY 1 // Support the lzma decompression algorighm. #define CONFIG_LZMA 1 // Support finding and running option roms during post. diff --git a/src/coreboot.c b/src/coreboot.c index 16f906a..4596ffd 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -503,7 +503,7 @@ cbfs_filename(struct cbfs_file *file) } // Determine the uncompressed size of a datafile. -int +u32 cbfs_datasize(struct cbfs_file *file, int iscomp) { void *src = (void*)file + ntohl(file->offset); diff --git a/src/disk.h b/src/disk.h index 89e4a2a..dbaa1b7 100644 --- a/src/disk.h +++ b/src/disk.h @@ -188,6 +188,7 @@ struct drive_s { #define DTYPE_FLOPPY 0x01 #define DTYPE_ATA 0x02 #define DTYPE_ATAPI 0x03 +#define DTYPE_RAMDISK 0x04 #define TRANSLATION_NONE 0 #define TRANSLATION_LBA 1 @@ -226,6 +227,8 @@ void drive_setup(); // floppy.c extern struct floppy_ext_dbt_s diskette_param_table2; void floppy_setup(); +void addFloppy(int floppyid, int ftype, int driver); +int find_floppy_type(u32 size); int process_floppy_op(struct disk_op_s *op); void floppy_tick(); @@ -240,4 +243,8 @@ void cdemu_13(struct bregs *regs); void cdemu_134b(struct bregs *regs); int cdrom_boot(int cdid); +// ramdisk.c +void ramdisk_setup(); +int process_ramdisk_op(struct disk_op_s *op); + #endif // disk.h diff --git a/src/floppy.c b/src/floppy.c index 3bf63b2..90a7fce 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -85,8 +85,8 @@ struct floppyinfo_s FloppyInfo[] VAR16_32 = { { {2, 40, 8}, 0x00, 0x27}, }; -static void -addFloppy(int floppyid, int ftype) +void +addFloppy(int floppyid, int ftype, int driver) { if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) { dprintf(1, "Bad floppy type %d\n", ftype); @@ -99,7 +99,7 @@ addFloppy(int floppyid, int ftype) Drives.drivecount++; memset(&Drives.drives[driveid], 0, sizeof(Drives.drives[0])); Drives.drives[driveid].cntl_id = floppyid; - Drives.drives[driveid].type = DTYPE_FLOPPY; + Drives.drives[driveid].type = driver; Drives.drives[driveid].blksize = FLOPPY_SECTOR_SIZE; Drives.drives[driveid].floppy_type = ftype; Drives.drives[driveid].sectors = (u16)-1; @@ -122,9 +122,9 @@ floppy_setup() } else { u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); if (type & 0xf0) - addFloppy(0, type >> 4); + addFloppy(0, type >> 4, DTYPE_FLOPPY); if (type & 0x0f) - addFloppy(1, type & 0x0f); + addFloppy(1, type & 0x0f, DTYPE_FLOPPY); } outb(0x02, PORT_DMA1_MASK_REG); @@ -132,6 +132,19 @@ floppy_setup() enable_hwirq(6, entry_0e); } +// Find a floppy type that matches a given image size. +int +find_floppy_type(u32 size) +{ + int i; + for (i=1; icylinders * c->heads * c->spt * FLOPPY_SECTOR_SIZE == size) + return i; + } + return -1; +} + /**************************************************************** * Low-level floppy IO diff --git a/src/memmap.c b/src/memmap.c index 005c474..45f5012 100644 --- a/src/memmap.c +++ b/src/memmap.c @@ -119,6 +119,23 @@ add_e820(u64 start, u64 size, u32 type) //dump_map(); } +// Find highest area of 32bit memory that can hold the given size. +struct e820entry * +find_high_area(u32 size) +{ + int i; + for (i=e820_count-1; i>=0; i--) { + struct e820entry *e = &e820_list[i]; + u64 end = e->start + e->size; + if (e->type != E820_RAM || end > 0xffffffff || e->size < size) + continue; + if (end < 1024*1024 + size) + break; + return e; + } + return NULL; +} + // Prep for memmap stuff - init bios table locations. void memmap_setup() diff --git a/src/memmap.h b/src/memmap.h index 51471d6..4494538 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -19,6 +19,7 @@ struct e820entry { void add_e820(u64 start, u64 size, u32 type); void memmap_setup(); void memmap_finalize(); +struct e820entry *find_high_area(u32 size); // e820 map storage (defined in system.c) extern struct e820entry e820_list[]; diff --git a/src/pmm.c b/src/pmm.c index b3eef4b..da462fd 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -6,7 +6,7 @@ #include "util.h" // checksum #include "config.h" // BUILD_BIOS_ADDR -#include "memmap.h" // e820_list +#include "memmap.h" // find_high_area #include "farptr.h" // GET_FARVAR #include "biosvar.h" // EBDA_SEGMENT_MINIMUM @@ -117,24 +117,14 @@ malloc_setup() ZoneTmpLow.top = ZoneTmpLow.cur = (u32)MAKE_FLATPTR(EBDA_SEGMENT_MINIMUM, 0); // Find memory at the top of ram. - u32 top = 0, bottom = 0; - int i; - for (i=e820_count-1; i>=0; i--) { - struct e820entry *e = &e820_list[i]; - u64 end = e->start + e->size; - if (e->type != E820_RAM || end > 0xffffffff - || e->size < CONFIG_MAX_HIGHTABLE + MALLOC_MIN_ALIGN) - continue; - top = end; - bottom = e->start; - break; - } - if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) { + struct e820entry *e = find_high_area(CONFIG_MAX_HIGHTABLE+MALLOC_MIN_ALIGN); + if (!e) { // No memory above 1Meg memset(&ZoneHigh, 0, sizeof(ZoneHigh)); - memset(&ZoneTmpHigh, 0, sizeof(ZoneHigh)); + memset(&ZoneTmpHigh, 0, sizeof(ZoneTmpHigh)); return; } + u32 top = e->start + e->size, bottom = e->start; // Memory at top of ram. ZoneHigh.bottom = ALIGN(top - CONFIG_MAX_HIGHTABLE, MALLOC_MIN_ALIGN); diff --git a/src/post.c b/src/post.c index 9bb5132..69aeb93 100644 --- a/src/post.c +++ b/src/post.c @@ -189,6 +189,7 @@ post() drive_setup(); floppy_setup(); ata_setup(); + ramdisk_setup(); optionrom_setup(); diff --git a/src/ramdisk.c b/src/ramdisk.c new file mode 100644 index 0000000..cb78f45 --- /dev/null +++ b/src/ramdisk.c @@ -0,0 +1,99 @@ +// Code for emulating a drive via high-memory accesses. +// +// Copyright (C) 2009 Kevin O'Connor +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "disk.h" // process_ramdisk_op +#include "util.h" // dprintf +#include "memmap.h" // add_e820 +#include "biosvar.h" // GET_GLOBAL +#include "bregs.h" // struct bregs + +#define RAMDISK_SECTOR_SIZE 512 + +void +ramdisk_setup() +{ + if (!CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY) + return; + + // Find image. + int iscomp; + struct cbfs_file *file = cbfs_finddataprefix("floppyimg/", NULL, &iscomp); + if (!file) + return; + u32 size = cbfs_datasize(file, iscomp); + dprintf(3, "Found floppy file %s of size %d\n", cbfs_filename(file), size); + int ftype = find_floppy_type(size); + if (ftype < 0) { + dprintf(3, "No floppy type found for ramdisk size\n"); + return; + } + + // Allocate ram for image. + struct e820entry *e = find_high_area(size); + if (!e) { + dprintf(3, "No ram for ramdisk\n"); + return; + } + u32 loc = e->start + e->size - size; + add_e820(loc, size, E820_RESERVED); + + // Copy image into ram. + cbfs_copyfile(file, (void*)loc, size, iscomp); + + // Setup driver. + dprintf(1, "Mapping CBFS floppy %s to addr %x\n", cbfs_filename(file), loc); + addFloppy(loc, ftype, DTYPE_RAMDISK); +} + +static int +ramdisk_op(struct disk_op_s *op, int iswrite) +{ + u32 offset = GET_GLOBAL(Drives.drives[op->driveid].cntl_id); + offset += (u32)op->lba * RAMDISK_SECTOR_SIZE; + u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl); + u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset); + + u64 gdt[6]; + if (iswrite) { + gdt[2] = opd; + gdt[3] = ramd; + } else { + gdt[2] = ramd; + gdt[3] = opd; + } + + // Call 0x1587 to copy data. + struct bregs br; + memset(&br, 0, sizeof(br)); + br.ah = 0x87; + br.es = GET_SEG(SS); + br.si = (u32)gdt; + br.cx = op->count * RAMDISK_SECTOR_SIZE / 2; + call16_int(0x15, &br); + + return DISK_RET_SUCCESS; +} + +int +process_ramdisk_op(struct disk_op_s *op) +{ + if (!CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY) + return 0; + + switch (op->command) { + case CMD_READ: + return ramdisk_op(op, 0); + case CMD_WRITE: + return ramdisk_op(op, 1); + case CMD_VERIFY: + case CMD_FORMAT: + case CMD_RESET: + return DISK_RET_SUCCESS; + default: + op->count = 0; + return DISK_RET_EPARAM; + } +} diff --git a/src/util.h b/src/util.h index dc3dfc1..0e4f84b 100644 --- a/src/util.h +++ b/src/util.h @@ -89,10 +89,10 @@ static inline u32 __ffs(u32 word) } // GDT bit manipulation -#define GDT_BASE(v) (((u64)((v) & 0xff000000) << 56) \ - | ((u64)((v) & 0x00ffffff) << 16)) -#define GDT_LIMIT(v) (((u64)((v) & 0x000f0000) << 48) \ - | ((u64)((v) & 0x0000ffff) << 0)) +#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ + | (((u64)(v) & 0x00ffffff) << 16)) +#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ + | (((u64)(v) & 0x0000ffff) << 0)) #define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set #define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set #define GDT_B (0x1ULL << 54) // Big flag @@ -224,7 +224,7 @@ struct cbfs_file; struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last); struct cbfs_file *cbfs_finddataprefix(const char *prefix, struct cbfs_file *last , int *iscomp); -int cbfs_datasize(struct cbfs_file *file, int iscomp); +u32 cbfs_datasize(struct cbfs_file *file, int iscomp); const char *cbfs_filename(struct cbfs_file *file); int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen, int iscomp); int cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev); -- 2.25.1