Page MenuHomeFreeBSD

D45404.diff
No OneTemporary

D45404.diff

diff --git a/stand/i386/libi386/Makefile b/stand/i386/libi386/Makefile
--- a/stand/i386/libi386/Makefile
+++ b/stand/i386/libi386/Makefile
@@ -7,6 +7,7 @@
SRCS+= biosacpi.c
SRCS+= biosdisk.c
SRCS+= biosmem.c
+SRCS+= biosmemdisk.c
SRCS+= biospci.c
SRCS+= biospnp.c
SRCS+= biossmap.c
diff --git a/stand/i386/libi386/biosmemdisk.c b/stand/i386/libi386/biosmemdisk.c
new file mode 100644
--- /dev/null
+++ b/stand/i386/libi386/biosmemdisk.c
@@ -0,0 +1,140 @@
+/*-
+ * Copyright (c) 2020 Richard Russo <russor@ruka.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * Source of information: https://repo.or.cz/syslinux.git
+ *
+ * Implements the MEMDISK protocol from syslinux, found in doc/memdisk.txt
+ * (search MEMDISK info structure). Since we validate the pointer to the mBFT, a
+ * minimum version of 3.85 is needed. Note: All this could be done in the
+ * kernel, since we don't have hooks to use this inside the boot loader. The
+ * details of these structures can be found in memdisk/memdisk.inc (search
+ * for mBFT).
+ *
+ * The kernel could just grab the mBFT table, but instead relies on us finding
+ * it and setting the right env variables.
+ */
+#include <stand.h>
+#include <machine/stdarg.h>
+#include <bootstrap.h>
+#include <btxv86.h>
+#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 mdi_length! */
+ uint16_t mdi_length;
+ uint8_t mdi_minor;
+ uint8_t mdi_major;
+ uint32_t 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; /* Code below assumes this is last */
+} __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));
+
+/*
+ * Maximum length of INT 13 entries we'll chase. Real disks are on this list,
+ * potentially, so we may have to look through them to find the memdisk.
+ */
+#define MEMDISK_MAX 32
+
+/*
+ * Scan for MEMDISK virtual block devices
+ */
+void
+biosmemdisk_detect(void)
+{
+ char line[80], scratch[80];
+ int hook = 0, count = 0, sector_size;
+ uint16_t segment, offset;
+ struct safe_13h_hook *probe;
+ ACPI_TABLE_HEADER *mbft;
+ uint8_t *cp, sum;
+ struct memdisk_info *mdi;
+
+ /*
+ * Walk through the int13 handler linked list, looking for possible
+ * MEMDISKs.
+ *
+ * The max is arbitrary to ensure termination.
+ */
+ offset = *(uint16_t *)PTOV(0x13 * 4);
+ segment = *(uint16_t *)PTOV(0x13 * 4 + 2);
+ while (hook < MEMDISK_MAX && !(segment == 0 && offset == 0)) {
+ /*
+ * Walk the linked list, making sure each node has the right
+ * signature and only looking at MEMDISK nodes.
+ */
+ probe = (struct safe_13h_hook *)PTOV(segment * 16 + offset);
+ if (memcmp(probe->sh_id, "$INT13SF", sizeof(probe->sh_id)) != 0) {
+ printf("Found int 13h unsafe hook at %p (%x:%x)\n",
+ probe, segment, offset);
+ break;
+ }
+ if (memcmp(probe->sh_vendor, "MEMDISK ", sizeof(probe->sh_vendor)) != 0)
+ goto end_of_loop;
+
+ /*
+ * If it is a memdisk, make sure the mBFT signature is correct
+ * and its checksum is right.
+ */
+ mbft = (ACPI_TABLE_HEADER *)PTOV(probe->sh_mbft);
+ if (memcmp(mbft->Signature, "mBFT", sizeof(mbft->Signature)) != 0)
+ goto end_of_loop;
+ sum = 0;
+ cp = (uint8_t *)mbft;
+ for (int idx = 0; idx < mbft->Length; ++idx)
+ sum += *(cp + idx);
+ if (sum != 0)
+ goto end_of_loop;
+
+ /*
+ * The memdisk info follows the ACPI_TABLE_HEADER in the mBFT
+ * section. If the sector size is present and non-zero use it
+ * otherwise assume 512.
+ */
+ mdi = (struct memdisk_info *)PTOV(probe->sh_mbft + sizeof(*mbft));
+ sector_size = 512;
+ 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 %#x (%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", 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++;
+end_of_loop:
+ hook++;
+ offset = probe->sh_next_offset;
+ segment = probe->sh_next_segment;
+ }
+}
diff --git a/stand/i386/libi386/libi386.h b/stand/i386/libi386/libi386.h
--- a/stand/i386/libi386/libi386.h
+++ b/stand/i386/libi386/libi386.h
@@ -149,3 +149,5 @@
vm_offset_t *kernend, int add_smap);
void pxe_enable(void *pxeinfo);
+
+void biosmemdisk_detect(void);
diff --git a/stand/i386/loader/main.c b/stand/i386/loader/main.c
--- a/stand/i386/loader/main.c
+++ b/stand/i386/loader/main.c
@@ -251,6 +251,9 @@
initial_bootinfo->bi_extmem = bios_extmem / 1024;
}
+ /* detect MEMDISK virtual disks */
+ biosmemdisk_detect();
+
/* detect SMBIOS for future reference */
smbios_detect(NULL);
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -89,6 +89,8 @@
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/disk.h>
+#include <sys/param.h>
+#include <sys/bus.h>
#include <geom/geom.h>
#include <geom/geom_int.h>
@@ -2082,8 +2084,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++)
@@ -2123,6 +2127,25 @@
sx_xunlock(&md_sx);
}
}
+
+ /*
+ * Load up to 32 pre-loaded disks
+ */
+ for (int i = 0; i < 32; i++) {
+ if (resource_long_value("md", i, "physaddr",
+ (long *) &paddr) != 0 ||
+ resource_int_value("md", i, "len", &len) != 0)
+ break;
+ ptr = (char *)pmap_map(NULL, paddr, paddr + len, VM_PROT_READ);
+ if (ptr != NULL && len != 0) {
+ sprintf(scratch, "preload%d 0x%016jx", i,
+ (uintmax_t)paddr);
+ sx_xlock(&md_sx);
+ md_preloaded(ptr, len, scratch);
+ sx_xunlock(&md_sx);
+ }
+ }
+
status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL,
0600, MDCTL_NAME);
g_topology_lock();

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 4:53 AM (10 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30799581
Default Alt Text
D45404.diff (6 KB)

Event Timeline