Index: stand/i386/libi386/Makefile =================================================================== --- stand/i386/libi386/Makefile +++ stand/i386/libi386/Makefile @@ -4,7 +4,7 @@ LIB= i386 -SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \ +SRCS= bio.c biosacpi.c biosdisk.c biosmem.c biosmemdisk.c biospnp.c \ biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \ comconsole.c devicename.c elf32_freebsd.c \ elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \ Index: stand/i386/libi386/biosmemdisk.c =================================================================== --- /dev/null +++ stand/i386/libi386/biosmemdisk.c @@ -0,0 +1,100 @@ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include "libi386.h" + +#include "platform/acfreebsd.h" +#include "acconfig.h" +#define ACPI_SYSTEM_XFACE +#include "actypes.h" +#include "actbl.h" + +struct memdisk_info { + uint32_t mdi_13h_hook_ptr; // not included in length! + uint16_t mdi_length; + uint8_t mdi_minor; + uint8_t mdi_major; + char *mdi_disk_ptr; + uint32_t mdi_disk_sectors; + uint32_t mdi_far_ptr_cmdline; + uint32_t mdi_old_int13h; + uint32_t mdi_old_int15h; + uint16_t mdi_dos_mem_before; + uint8_t mdi_boot_loader_id; + uint8_t mdi_sector_size; +} __attribute__((packed)); + +struct safe_13h_hook { + char sh_jmp[3]; + char sh_id[8]; + char sh_vendor[8]; + uint16_t sh_next_offset; + uint16_t sh_next_segment; + uint32_t sh_flags; + uint32_t sh_mbft; +} __attribute__((packed)); + +/* + * Scan for MEMDISK virtual block devices + */ + +void +biosmemdisk_detect() +{ + char line[80], scratch[80]; + int idx, hook = 0, count = 0, sector_size; + uint16_t segment, offset; + struct safe_13h_hook *probe; + ACPI_TABLE_HEADER *mbft; + uint8_t *cp, sum; + + offset = *(uint16_t *)PTOV(0x4C); // int 13H handler in interrupt vector table + segment = *(uint16_t *)PTOV(0x4C + 2); + + while (hook < 32 && !(segment == 0 && offset == 0)) { + probe = (struct safe_13h_hook*)PTOV(segment * 16 + offset); + if (memcmp(probe->sh_id, "$INT13SF", sizeof(probe->sh_id)) == 0) { + if (memcmp(probe->sh_vendor, "MEMDISK ", sizeof(probe->sh_vendor)) == 0) { + mbft = (ACPI_TABLE_HEADER *)PTOV(probe->sh_mbft); + if (memcmp(mbft->Signature, "mBFT", sizeof(mbft->Signature)) == 0) { + cp = (uint8_t *)mbft; + sum = 0; + for (idx = 0; idx < mbft->Length; ++idx) + sum += *(cp + idx); + if (sum == 0) { + struct memdisk_info *mdi = (struct memdisk_info *)PTOV(probe->sh_mbft + sizeof(*mbft)); + sector_size = 512; // assume 512 unless MEMDISK struct is from 3.71+ and is non-zero)) + if (mdi->mdi_length + sizeof(mdi->mdi_13h_hook_ptr) >= sizeof(*mdi) && mdi->mdi_sector_size != 0) { + sector_size = 1 << mdi->mdi_sector_size; + } + + printf("memdisk %d.%d disk at %p (%d sectors = %d bytes)\n", + mdi->mdi_major, mdi->mdi_minor, + mdi->mdi_disk_ptr, mdi->mdi_disk_sectors, mdi->mdi_disk_sectors * sector_size); + + snprintf(line, sizeof(line), "hint.md.%d.physaddr", count); + snprintf(scratch, sizeof(scratch), "0x%08x", (vm_offset_t)mdi->mdi_disk_ptr); + setenv(line, scratch, 1); + snprintf(line, sizeof(line), "hint.md.%d.len", count); + snprintf(scratch, sizeof(scratch), "%d", mdi->mdi_disk_sectors * sector_size); + setenv(line, scratch, 1); + ++count; + } + } + + } else { + printf("Found int 13h safe hook at %p, vendor %.8s\n", probe, probe->sh_vendor); + } + offset = probe->sh_next_offset; + segment = probe->sh_next_segment; + } else { + printf("Found int 13h unsafe hook at %p (%x:%x)\n", probe, segment, offset); + segment = offset = 0; + } + ++hook; + } +} Index: stand/i386/libi386/libi386.h =================================================================== --- stand/i386/libi386/libi386.h +++ stand/i386/libi386/libi386.h @@ -154,3 +154,5 @@ vm_offset_t *kernend, int add_smap); void pxe_enable(void *pxeinfo); + +void biosmemdisk_detect(void); Index: stand/i386/loader/main.c =================================================================== --- stand/i386/loader/main.c +++ stand/i386/loader/main.c @@ -256,6 +256,9 @@ extract_currdev(); /* set $currdev and $loaddev */ bios_getsmap(); + + /* detect MEMDISK virtual disks */ + biosmemdisk_detect(); interact(); Index: sys/dev/md/md.c =================================================================== --- sys/dev/md/md.c +++ sys/dev/md/md.c @@ -92,6 +92,8 @@ #include #include #include +#include +#include #include #include @@ -2027,8 +2029,10 @@ { caddr_t mod; u_char *ptr, *name, *type; + u_char scratch[40]; unsigned len; int i; + vm_offset_t paddr; /* figure out log2(NINDIR) */ for (i = NINDIR, nshift = -1; i; nshift++) @@ -2068,6 +2072,23 @@ sx_xunlock(&md_sx); } } + + for (i = 0; i < 32; ++i) { + if (resource_long_value("md", i, "physaddr", (signed long*) &paddr) != 0 || + resource_int_value("md", i, "len", (signed *)&len) != 0) { + + break; + } + + ptr = (char *)pmap_map(NULL, paddr, paddr + len, VM_PROT_READ); + if (ptr != NULL && len != 0) { + sprintf(scratch, "preload%d 0x%016lx", i, paddr); + sx_xlock(&md_sx); + md_preloaded(ptr, len, scratch); + sx_xunlock(&md_sx); + } + } + md_pbuf_zone = pbuf_zsecond_create("mdpbuf", nswbuf / 10); status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL, 0600, MDCTL_NAME);