code:
/*	$OpenBSD: biosdev.h,v 1.33 2011/03/14 22:14:40 krw Exp $	*/

/*
 * Copyright (c) 1996 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

/*
 * Extension support bitmap definition (returned by 41h)
 */
#define EXT_BM_EDA	0x01	/* Extended disk access functions	*/
				/*  (42h-44h, 47h and 48h) supported.	*/
#define EXT_BM_RDC	0x02	/* Removable drive controller functions	*/
				/*  (45h, 46h, 48h, 49h and INT 15 52h)	*/
				/*  supported.				*/
#define EXT_BM_EDD	0x04	/* Enhanced disk drive functions	*/
				/*  (48h and 4eh) supported.		*/
#define EXT_BM_RSV	0xf8	/* Reserved (0)				*/

struct consdev;
struct open_file;

/* biosdev.c */
extern const char *biosdevs[];
int biosstrategy(void *, int, daddr32_t, size_t, void *, size_t *);
int biosopen(struct open_file *, ...);
int biosclose(struct open_file *);
int biosioctl(struct open_file *, u_long, void *);
int bios_getdiskinfo(int, bios_diskinfo_t *);
int biosd_io(int, bios_diskinfo_t *, u_int, int, void *);
const char * bios_getdisklabel(bios_diskinfo_t *, struct disklabel *);

/* diskprobe.c */
struct diskinfo *dklookup(int);
bios_diskinfo_t *bios_dklookup(int);

/* bioscons.c */
void pc_probe(struct consdev *);
void pc_init(struct consdev *);
int pc_getc(dev_t);
int pc_getshifts(dev_t);
void pc_putc(dev_t, int);
void pc_pollc(dev_t, int);
void com_probe(struct consdev *);
void com_init(struct consdev *);
int comspeed(dev_t, int);
int com_getc(dev_t);
void com_putc(dev_t, int);
void com_pollc(dev_t, int);


code:
/*	$OpenBSD: biosprobe.c,v 1.5 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 2002 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <machine/biosvar.h>
#include <machine/pio.h>
#include <dev/cons.h>
#include <sys/disklabel.h>
#include "disk.h"
#include "debug.h"
#include "libsa.h"
#include "biosdev.h"

void *
getSYSCONFaddr(void)
{
	u_int32_t status;
	u_int8_t *vers;

	__asm volatile(DOINT(0x15) "\n\t"
	    "setc %%al\n\t"
	    : "=a" (status)
	    : "0" (0xC000)
	    : "%ebx", "%ecx", "%edx", "%esi", "%edi", "cc");

	/* On failure we go for a NULL */
	if (status)
		return NULL;

	/* Calculate where the version bytes are */
	vers = (void*)((BIOS_regs.biosr_es << 4) | BIOS_regs.biosr_bx);
	return vers;
}

void *
getEBDAaddr(void)
{
	u_int32_t status;
	u_int8_t *info;

	info = getSYSCONFaddr();

	if (!info)
		return NULL;

	__asm volatile(DOINT(0x15) "\n\t"
	    "setc %%al"
	    : "=a" (status)
	    : "0" (0xC100)
	    : "%ebx", "%ecx", "%edx", "%esi", "%edi", "cc");

	if (status)
		return NULL;

	info = (void *)(BIOS_regs.biosr_es << 4);

	return info;
}

license: unknown


code:
/*	$OpenBSD: cmd_i386.c,v 1.33 2013/10/23 05:05:19 mlarkin Exp $	*/

/*
 * Copyright (c) 1997-1999 Michael Shalayeff
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <sys/reboot.h>
#include <machine/biosvar.h>
#include <sys/disklabel.h>
#include "disk.h"
#include "debug.h"
#include "biosdev.h"
#include "libsa.h"
#include <cmd.h>

extern const char version[];

int Xboot(void);
int Xcomaddr(void);
int Xdiskinfo(void);
int Xmemory(void);
int Xregs(void);

/* From gidt.S */
int bootbuf(void *, int);

const struct cmd_table cmd_machine[] = {
	{ "boot",	CMDT_CMD, Xboot },
	{ "comaddr",	CMDT_CMD, Xcomaddr },
	{ "diskinfo",	CMDT_CMD, Xdiskinfo },
	{ "memory",	CMDT_CMD, Xmemory },
#ifdef DEBUG
	{ "regs",	CMDT_CMD, Xregs },
#endif
	{ NULL, 0 }
};

int
Xdiskinfo(void)
{
#ifndef _TEST
	dump_diskinfo();
#endif
	return 0;
}

#ifdef DEBUG
int
Xregs(void)
{
	DUMP_REGS;
	return 0;
}
#endif

int
Xboot(void)
{
#ifndef _TEST
	int dev, part, st;
	bios_diskinfo_t *bd = NULL;
	char buf[DEV_BSIZE], *dest = (void *)BOOTBIOS_ADDR;

	if (cmd.argc != 2) {
		printf("machine boot {fd,hd}<0123>[abcd]\n");
		printf("Where [0123] is the disk number,"
		    " and [abcd] is the partition.\n");
		return 0;
	}

	/* Check arg */
	if (cmd.argv[1][0] != 'f' && cmd.argv[1][0] != 'h')
		goto bad;
	if (cmd.argv[1][1] != 'd')
		goto bad;
	if (cmd.argv[1][2] < '0' || cmd.argv[1][2] > '3')
		goto bad;
	if ((cmd.argv[1][3] < 'a' || cmd.argv[1][3] > 'd') &&
	    cmd.argv[1][3] != '\0')
		goto bad;

	printf("Booting from %s ", cmd.argv[1]);

	dev = (cmd.argv[1][0] == 'h')?0x80:0;
	dev += (cmd.argv[1][2] - '0');
	part = (cmd.argv[1][3] - 'a');

	if (part > 0)
		printf("[%x,%d]\n", dev, part);
	else
		printf("[%x]\n", dev);

	/* Read boot sector from device */
	bd = bios_dklookup(dev);
	st = biosd_io(F_READ, bd, 0, 1, buf);
	if (st)
		goto bad;

	/* Frob boot flag in buffer from HD */
	if ((dev & 0x80) && (part > 0)){
		int i, j;

		for (i = 0, j = DOSPARTOFF; i < 4; i++, j += 16)
			if (part == i)
				buf[j] |= 0x80;
			else
				buf[j] &= ~0x80;
	}

	/* Load %dl, ljmp */
	bcopy(buf, dest, DEV_BSIZE);
	bootbuf(dest, dev);

bad:
	printf("Invalid device!\n");
#endif
	return 0;
}

int
Xmemory(void)
{
	if (cmd.argc >= 2) {
		int i;
		/* parse the memory specs */

		for (i = 1; i < cmd.argc; i++) {
			char *p;
			long long addr, size;

			p = cmd.argv[i];

			size = strtoll(p + 1, &p, 0);
			/* Size the size */
			switch (*p) {
				case 'G':
				case 'g':
					size *= 1024;
				case 'M':
				case 'm':
					size *= 1024;
				case 'K':
				case 'k':
					size *= 1024;
					p++;
			}

			/* Handle (possibly non-existant) address part */
			switch (*p) {
				case '@':
					addr = strtoll(p + 1, NULL, 0);
					break;

				/* Adjust address if we don't need it */
				default:
					if (cmd.argv[i][0] == '=')
						addr = -1;
					else
						addr = 0;
			}

			if (addr == 0 || size == 0) {
				printf("bad language\n");
				return 0;
			} else {
				switch (cmd.argv[i][0]) {
				case '-':
					mem_delete(addr, addr + size);
					break;
				case '+':
					mem_add(addr, addr + size);
					break;
				case '=':
					mem_limit(size);
					break;
				default :
					printf("bad OP\n");
					return 0;
				}
			}
		}
	}

	dump_biosmem(NULL);

	return 0;
}

int
Xcomaddr(void)
{
	extern int com_addr;

	if (cmd.argc >= 2)
		com_addr = (int)strtol(cmd.argv[1], NULL, 0);

	return 0;
}


code:
/*	$OpenBSD: cpuprobe.c,v 1.2 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 2004 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <machine/psl.h>
#include <machine/specialreg.h>

#include "libsa.h"

int amd64_supported;
static int cpu_family, cpu_model, cpu_stepping;
static int psl_check;
static u_int32_t feature_ecx, feature_edx, feature_amd;
static char cpu_brandstr[48];		/* Includes term NUL byte */
static char cpu_vendor[13];		/* 12 chars plus NUL term */

/*
 * cpuid instruction.  request in eax, result in eax, ebx, ecx, edx.
 * requires caller to provide u_int32_t regs[4] array.
 */
u_int32_t
cpuid(u_int32_t eax, u_int32_t *regs)
{
	__asm volatile(
	    "cpuid\n\t"
	    "movl	%%eax, 0(%2)\n\t"
	    "movl	%%ebx, 4(%2)\n\t"
	    "movl	%%ecx, 8(%2)\n\t"
	    "movl	%%edx, 12(%2)\n\t"
	    : "=a" (eax)
	    : "0" (eax), "S" (regs)
	    : "bx", "cx", "dx");

	return eax;
}

void
cpuprobe(void)
{
	u_int32_t cpuid_max, extended_max;
	u_int32_t regs[4];

	/*
	 * The following is a simple check to see if cpuid is supported.
	 * We try to toggle bit 21 (PSL_ID) in eflags.  If it works, then
	 * cpuid is supported.  If not, there's no cpuid, and we don't
	 * try it (don't want /boot to get an invalid opcode exception).
	 *
	 * XXX The NexGen Nx586 does not support this bit, so this is not
	 *     a good method to detect the presence of cpuid on this
	 *     processor.  That's fine: the purpose here is to detect the
	 *     absence of cpuid.  We don't mind if the instruction's not
	 *     there - this is not intended to determine exactly what
	 *     processor is there, just whether it's i386 or amd64.
	 *
	 *     The only thing that would cause us grief is a processor which
	 *     does not support cpuid but which does allow the PSL_ID bit
	 *     in eflags to be toggled.
	 */
	__asm volatile(
	    "pushfl\n\t"
	    "popl	%2\n\t"
	    "xorl	%2, %0\n\t"
	    "pushl	%0\n\t"
	    "popfl\n\t"
	    "pushfl\n\t"
	    "popl	%0\n\t"
	    "xorl	%2, %0\n\t"		/* If %2 == %0, no cpuid */
	    : "=r" (psl_check)
	    : "0" (PSL_ID), "r" (0)
	    : "cc");

	if (psl_check == PSL_ID) {			/* cpuid supported */
		cpuid_max = cpuid(0, regs);		/* Highest std call */

		bcopy(&regs[1], cpu_vendor, sizeof(regs[1]));
		bcopy(&regs[3], cpu_vendor + 4, sizeof(regs[3]));
		bcopy(&regs[2], cpu_vendor + 8, sizeof(regs[2]));
		cpu_vendor[sizeof(cpu_vendor) - 1] = '\0';

		if (cpuid_max >= 1) {
			u_int32_t id;

			id = cpuid(1, regs);		/* Get basic info */
			cpu_stepping = id & 0x000000f;
			cpu_model = (id >> 4) & 0x0000000f;
			cpu_family = (id >> 8) & 0x0000000f;

			feature_ecx = regs[2];
			feature_edx = regs[3];
		}

		extended_max = cpuid(0x80000000, regs);	/* Highest ext  */

		if (extended_max >= 0x80000001) {
			cpuid(0x80000001, regs);
			feature_amd = regs[3];
			if (feature_amd & CPUID_LONG)
				amd64_supported = 1;
		}

		cpu_brandstr[0] = '\0';
		if (extended_max >= 0x80000004) {
			u_int32_t brand_ints[12];

			cpuid(0x80000002, brand_ints);
			cpuid(0x80000003, brand_ints + 4);
			cpuid(0x80000004, brand_ints + 8);

			bcopy(brand_ints, cpu_brandstr,
			    sizeof(cpu_brandstr) - 1);

			cpu_brandstr[sizeof(cpu_brandstr) - 1] = '\0';
		}
	}

	printf("%s", amd64_supported ? " amd64" : " i386");
}

void
dump_cpuinfo(void)
{
	printf("\"%s\", family %d, model %d, step %d\n",
	    cpu_vendor, cpu_family, cpu_model, cpu_stepping);

	if (*cpu_brandstr)
		printf("%s\n", cpu_brandstr);

	printf("features: ecx 0x%x, edx 0x%x, amd 0x%x\n",
	    feature_ecx, feature_edx, feature_amd);

	printf("psl_check: 0x%x\n", psl_check);
}


code:
/*	$OpenBSD: cpuprobe.h,v 1.1 2004/06/26 05:19:37 tom Exp $	*/

/*
 * Copyright (c) 2004 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _CPUPROBE_H
#define _CPUPROBE_H

void dump_cpuinfo(void);

#endif	/* _CPUPROBE_H */


code:
/*	$OpenBSD: debug.c,v 1.16 2010/12/06 22:51:46 jasper Exp $	*/

/*
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <lib/libsa/stand.h>
#include <debug.h>
#include <dev/cons.h>

#define	VBASE	(0xb8000)

char *const reg_names[] = { REG_NAMES };
const int nreg = nitems(reg_names);
struct reg reg;
u_int32_t *const reg_values[] = { REG_VALUES(reg) };
char *const trap_names[] = { TRAP_NAMES };

void d_putc(dev_t, int);

#ifdef DEBUG_DEBUG
#define	CKPT(c)	(*(u_short volatile *)(VBASE+160) = (0x1700 | (c)))
#else
#define	CKPT(c)	/* c */
#endif

void
debug_init(void)
{
}

void
dump_regs(u_int trapno, u_int arg)
{
	register int i;
	/* make it local, so it won't rely on .data/.bss corruption */
	struct consdev d_cons, *save_cons;

	/* init cons mod */
	save_cons = cn_tab;
	bzero(&d_cons, sizeof(d_cons));
	d_cons.cn_putc = &d_putc;
	cn_tab = &d_cons;

	/* Trap info */
	printf("\ftrap: %u(%x): %s\ncn_tab=%p\n",
	    trapno, arg, trap_names[trapno], save_cons);

	/* Register dump */
	for (i = 1; i <= nreg; i++)
		printf("%s\t%x%c", reg_names[i-1], *reg_values[i-1],
		    ((i%4)? ' ': '\n'));

	dump_mem("Code dump", (void *)*reg_values[8], 8);
	/* %ebx (void *)((*reg_values[3] + 15) & ~0x0F) */
	dump_mem("Memory dump", (void *)0x1a000, 48);
	dump_mem("Stack trace", (void *)(*reg_values[4]), 48);

	/* restore the console */
	cn_tab = save_cons;
}

void
dump_mem(char *l, void *p, size_t n)
{
	register int i;

	printf("%s [%p]:%s", l, p, (n > 6? "\n":" "));
	for (i = 1; i <= n; i++)
		printf("%x%c", *(u_int32_t *)p++, ((i%8)? ' ': '\n'));
	if (n % 8)
		printf("\n");
}

u_int d_pos;

void
d_putc(dev_t d, int c)
{
	switch (c) {
	case '\n':	d_pos += 80;					break;
	case '\r':	d_pos -= d_pos % 80;				break;
	case '\b':	d_pos--;					break;
	case '\f':	bzero((void *)VBASE, 80*25*2); d_pos = 0;	break;
		/* print it */
	default:
		((u_int16_t volatile *)VBASE)[d_pos++] = 0x0700 | (u_char)c;
		break;
	}
}


code:
/*	$OpenBSD: debug.h,v 1.7 2004/02/10 00:41:44 tom Exp $	*/

/*
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <debug_md.h>
#include <machine/reg.h>

extern char  *const reg_names[];
extern const size_t nregs;

void debug_init(void);
void dump_regs(u_int, u_int);
void dump_mem(char *, void *, size_t);


code:
/*	$OpenBSD: debug_i386.S,v 1.12 2004/03/09 19:12:12 tom Exp $	*/

/*
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <machine/asm.h>
#include <machine/psl.h>
#define _LOCORE
#include <machine/segments.h>
#include <machine/trap.h>
#include <debug_md.h>
#undef _LOCORE

	/* do this way because some cpus (like cyrix 6x86) store garbage
	 * into high word, instead of zeroes.
	 */
#define	pushsr(sr)	movl sr, %eax; pushl %eax

	.text
	.globl	alltraps

alltraps:
	pushal
	pushsr(%ds)
	pushsr(%es)
	pushsr(%fs)
	pushsr(%gs)
		/* muck %cs, see note about pushsr() above */
	movl	0xf*4(%esp), %eax
	movzwl	%ax, %eax
	movl	%eax, 0xf*4(%esp)
#ifdef DEBUG_DEBUG
	movl	$0xb8280, %edi
	movl	0x0c*4(%esp), %eax	/* trapno */
	addb	$'0', %al
	movb	$0x17, %ah
	shll	$16, %eax
	movb	0x0d*4(%esp), %al	/* error */
	addb	$'0', %al
	movb	$0x17, %ah
	movl	%eax, (%edi)
#endif
	call	_C_LABEL(check_regs)
#ifdef DEBUG_DEBUG
	movl	$0xb8290, %edi
	movl	$0x47394738, (%edi)
#endif
	popl	%gs
	popl	%fs
	popl	%es
	popl	%ds
	popal
	addl	$0x8, %esp
	hlt
	iret

ENTRY(check_regs)
#ifdef DEBUG_DEBUG
	movl	$0xb8284, %edi
	movl	$0x47334732, (%edi)
#endif
	movl	$0x10, %eax
	mov	%ax, %ds
	mov	%ax, %es
	movl	$reg, %edi
	cld
	movl	0x0c*4(%esp), %eax; stosl /* %eax	*/
	movl	0x0b*4(%esp), %eax; stosl /* %ecx	*/
	movl	0x0a*4(%esp), %eax; stosl /* %edx	*/
	movl	0x09*4(%esp), %eax; stosl /* %ebx	*/
	movl	0x08*4(%esp), %eax; stosl /* %esp	*/
	movl	0x07*4(%esp), %eax; stosl /* %ebp	*/
	movl	0x06*4(%esp), %eax; stosl /* %esi	*/
	movl	0x05*4(%esp), %eax; stosl /* %edi	*/
	movl	0x0f*4(%esp), %eax; stosl /* %eip	*/
	movl	0x11*4(%esp), %eax; stosl /* %eflags	*/
	movl	0x10*4(%esp), %eax; stosl /* %cs	*/
	mov		%ss,  %ax ; stosl /* %ss	*/
	movl	0x04*4(%esp), %eax; stosl /* %ds	*/
	movl	0x03*4(%esp), %eax; stosl /* %es	*/
	movl	0x02*4(%esp), %eax; stosl /* %fs	*/
	movl	0x01*4(%esp), %eax; stosl /* %gs	*/

#ifdef DEBUG_DEBUG
	movl	$0xb8288, %edi
	movl	$0x47354734, (%edi)
#endif
	movl	0x0e*4(%esp), %ecx	/* error */
	movl	0x0d*4(%esp), %eax	/* trapno */
	pushl	%ecx
	pushl	%eax
	call	_C_LABEL(dump_regs)
	popl	%eax
	popl	%eax

#ifdef DEBUG_DEBUG
	movl	$0xb828c, %edi
	movl	$0x47374736, (%edi)
#endif
	ret


code:
/*	$OpenBSD: debug_md.h,v 1.7 2006/06/06 13:30:42 mickey Exp $	*/

/*
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#define	REG_NAMES	\
	"eax", "ecx", "edx", "ebx", "esp", \
	"ebp", "esi", "edi", "eip", "eflags", \
	"cs",  "ss",  "ds",  "es",  "fs", \
	"gs"
#define REG_VALUES(r)	\
	&(r).r_eax, &(r).r_ecx, &(r).r_edx, &(r).r_ebx, &(r).r_esp, \
	&(r).r_ebp, &(r).r_esi, &(r).r_edi, &(r).r_eip, &(r).r_eflags, \
	&(r).r_cs , &(r).r_ss,  &(r).r_ds,  &(r).r_es,  &(r).r_fs, \
	&(r).r_gs
#define TRAP_NAMES	\
	"invalid opcode fault", "breakpoint trap", "arithmetic trap", \
	"asynchronous system trap", "protection fault", "trace trap", \
	"page fault", "alignment fault", "integer divide fault", \
	"non-maskable interrupt", "overflow trap", "bounds check fault", \
	"device not available fault", "double fault", \
	"fp coprocessor operand fetch fault (![P]Pro)", "invalid tss fault", \
	"segment not present fault", "stack fault", "machine check ([P]Pro)", \
	"reserved fault base"

#ifdef	_LOCORE
	.globl	_C_LABEL(reg)
#define DUMP_REGS	int $2
#else
#define DUMP_REGS	__asm("int $2")
extern struct reg reg;
#endif


code:
/*	$OpenBSD: dev_i386.c,v 1.40 2014/07/13 09:26:08 jasper Exp $	*/

/*
 * Copyright (c) 1996-1999 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <sys/queue.h>
#include <sys/disklabel.h>
#include <dev/cons.h>

#include "libsa.h"
#include "biosdev.h"
#include "disk.h"

#ifdef SOFTRAID
#include <dev/biovar.h>
#include <dev/softraidvar.h>
#include "softraid.h"
#endif

extern int debug;

/* XXX use slot for 'rd' for 'hd' pseudo-device */
const char bdevs[][4] = {
	"wd", "", "fd", "", "sd", "st", "cd", "",
	"", "", "", "", "", "", "", "", "", "hd", ""
};
const int nbdevs = nitems(bdevs);

const char cdevs[][4] = {
	"cn", "", "", "", "", "", "", "",
	"com", "", "", "", "pc"
};
const int ncdevs = nitems(cdevs);

/* pass dev_t to the open routines */
int
devopen(struct open_file *f, const char *fname, char **file)
{
	struct devsw *dp = devsw;
	register int i, rc = 1;

	*file = (char *)fname;

#ifdef DEBUG
	if (debug)
		printf("devopen:");
#endif

	for (i = 0; i < ndevs && rc != 0; dp++, i++) {
#ifdef DEBUG
		if (debug)
			printf(" %s: ", dp->dv_name);
#endif
		if ((rc = (*dp->dv_open)(f, file)) == 0) {
			f->f_dev = dp;
			return 0;
		}
#ifdef DEBUG
		else if (debug)
			printf("%d", rc);
#endif

	}
#ifdef DEBUG
	if (debug)
		putchar('\n');
#endif

	if ((f->f_flags & F_NODEV) == 0)
		f->f_dev = dp;

	return rc;
}

void
devboot(dev_t bootdev, char *p)
{
#ifdef SOFTRAID
	struct sr_boot_volume *bv;
	struct sr_boot_chunk *bc;
	struct diskinfo *dip = NULL;
#endif
	int sr_boot_vol = -1;
	int part_type = FS_UNUSED;

#ifdef _TEST
	*p++ = '/';
	*p++ = 'd';
	*p++ = 'e';
	*p++ = 'v';
	*p++ = '/';
	*p++ = 'r';
#endif

#ifdef SOFTRAID
	/*
	 * Determine the partition type for the 'a' partition of the
	 * boot device.
	 */
	TAILQ_FOREACH(dip, &disklist, list)
		if (dip->bios_info.bios_number == bootdev &&
		    (dip->bios_info.flags & BDI_BADLABEL) == 0)
			part_type = dip->disklabel.d_partitions[0].p_fstype;

	/*
	 * See if we booted from a disk that is a member of a bootable
	 * softraid volume.
	 */
	SLIST_FOREACH(bv, &sr_volumes, sbv_link) {
		if (bv->sbv_flags & BIOC_SCBOOTABLE)
			SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link)
				if (bc->sbc_disk == bootdev)
					sr_boot_vol = bv->sbv_unit;
		if (sr_boot_vol != -1)
			break;
	}
#endif

	if (sr_boot_vol != -1 && part_type != FS_BSDFFS) {
		*p++ = 's';
		*p++ = 'r';
		*p++ = '0' + sr_boot_vol;
	} else if (bootdev & 0x100) {
		*p++ = 'c';
		*p++ = 'd';
		*p++ = '0';
	} else {
		if (bootdev & 0x80)
			*p++ = 'h';
		else
			*p++ = 'f';
		*p++ = 'd';
		*p++ = '0' + (bootdev & 0x7f);
	}
	*p++ = 'a';
	*p = '\0';
}

char ttyname_buf[8];

char *
ttyname(int fd)
{
	snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d",
	    cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev));

	return ttyname_buf;
}

dev_t
ttydev(char *name)
{
	int i, unit = -1;
	char *no = name + strlen(name) - 1;

	while (no >= name && *no >= '0' && *no <= '9')
		unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0';
	if (no < name || unit < 0)
		return NODEV;
	for (i = 0; i < ncdevs; i++)
		if (strncmp(name, cdevs[i], no - name + 1) == 0)
			return makedev(i, unit);
	return NODEV;
}

int
cnspeed(dev_t dev, int sp)
{
	if (major(dev) == 8)	/* comN */
		return comspeed(dev, sp);

	/* pc0 and anything else */
	return 9600;
}


code:
/*	$OpenBSD: disk.h,v 1.5 2012/10/31 13:55:58 jsing Exp $	*/

/*
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _DISK_H
#define _DISK_H

#include <sys/queue.h>

/* All the info on a disk we've found */
struct diskinfo {
	bios_diskinfo_t bios_info;
	struct disklabel disklabel;
	struct sr_boot_volume *sr_vol;

	dev_t bsddev, bootdev;

	TAILQ_ENTRY(diskinfo) list;
};
TAILQ_HEAD(disklist_lh, diskinfo);

/* Disk info for boot device. */
extern struct diskinfo *bootdev_dip;

/* List of probed disks. */
extern struct disklist_lh disklist;

void dump_diskinfo(void);

#endif /* _DISK_H */


code:
/*	$OpenBSD: diskprobe.c,v 1.39 2014/07/12 20:58:31 tedu Exp $	*/

/*
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

/* We want the disk type names from disklabel.h */
#undef DKTYPENAMES

#include <sys/param.h>
#include <sys/queue.h>
#include <sys/reboot.h>
#include <sys/disklabel.h>

#include <lib/libz/zlib.h>
#include <machine/biosvar.h>
#include <stand/boot/bootarg.h>

#include "disk.h"
#include "biosdev.h"
#include "libsa.h"

#ifdef SOFTRAID
#include "softraid.h"
#endif

#define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE	/* Max # of blks to cksum */

/* Local Prototypes */
static int disksum(int);

/* List of disk devices we found/probed */
struct disklist_lh disklist;

/* Pointer to boot device */
struct diskinfo *bootdev_dip;

extern int debug;
extern int bios_bootdev;
extern int bios_cddev;

/* Probe for all BIOS floppies */
static void
floppyprobe(void)
{
	struct diskinfo *dip;
	int i;

	/* Floppies */
	for (i = 0; i < 4; i++) {
		dip = alloc(sizeof(struct diskinfo));
		bzero(dip, sizeof(*dip));

		if (bios_getdiskinfo(i, &dip->bios_info)) {
#ifdef BIOS_DEBUG
			if (debug)
				printf(" <!fd%u>", i);
#endif
			free(dip, 0);
			break;
		}

		printf(" fd%u", i);

		/* Fill out best we can - (fd?) */
		dip->bios_info.bsd_dev = MAKEBOOTDEV(2, 0, 0, i, RAW_PART);

		/*
		 * Delay reading the disklabel until we're sure we want
		 * to boot from the floppy. Doing this avoids a delay
		 * (sometimes very long) when trying to read the label
		 * and the drive is unplugged.
		 */
		dip->bios_info.flags |= BDI_BADLABEL;

		/* Add to queue of disks */
		TAILQ_INSERT_TAIL(&disklist, dip, list);
	}
}

/* Probe for all BIOS hard disks */
static void
hardprobe(void)
{
	struct diskinfo *dip;
	int i;
	u_int bsdunit, type;
	u_int scsi = 0, ide = 0;
	const char *dc = (const char *)((0x40 << 4) + 0x75);

	/* Hard disks */
	for (i = 0x80; i < (0x80 + *dc); i++) {
		dip = alloc(sizeof(struct diskinfo));
		bzero(dip, sizeof(*dip));

		if (bios_getdiskinfo(i, &dip->bios_info)) {
#ifdef BIOS_DEBUG
			if (debug)
				printf(" <!hd%u>", i&0x7f);
#endif
			free(dip, 0);
			break;
		}

		printf(" hd%u%s", i&0x7f, (dip->bios_info.bios_edd > 0?"+":""));

		/* Try to find the label, to figure out device type */
		if ((bios_getdisklabel(&dip->bios_info, &dip->disklabel)) ) {
			printf("*");
			bsdunit = ide++;
			type = 0;	/* XXX let it be IDE */
		} else {
			/* Best guess */
			switch (dip->disklabel.d_type) {
			case DTYPE_SCSI:
				type = 4;
				bsdunit = scsi++;
				dip->bios_info.flags |= BDI_GOODLABEL;
				break;

			case DTYPE_ESDI:
			case DTYPE_ST506:
				type = 0;
				bsdunit = ide++;
				dip->bios_info.flags |= BDI_GOODLABEL;
				break;

			default:
				dip->bios_info.flags |= BDI_BADLABEL;
				type = 0;	/* XXX Suggest IDE */
				bsdunit = ide++;
			}
		}

		dip->bios_info.checksum = 0; /* just in case */
		/* Fill out best we can */
		dip->bios_info.bsd_dev =
		    MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART);

		/* Add to queue of disks */
		TAILQ_INSERT_TAIL(&disklist, dip, list);
	}
}

/* Probe for all BIOS supported disks */
u_int32_t bios_cksumlen;
void
diskprobe(void)
{
	struct diskinfo *dip;
	int i;

	/* These get passed to kernel */
	bios_diskinfo_t *bios_diskinfo;

	/* Init stuff */
	TAILQ_INIT(&disklist);

	/* Do probes */
	floppyprobe();
#ifdef BIOS_DEBUG
	if (debug)
		printf(";");
#endif
	hardprobe();

#ifdef SOFTRAID
	srprobe();
#endif

	/* Checksumming of hard disks */
	for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
		;
	bios_cksumlen = i;

	/* Get space for passing bios_diskinfo stuff to kernel */
	for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
	    dip = TAILQ_NEXT(dip, list))
		i++;
	bios_diskinfo = alloc(++i * sizeof(bios_diskinfo_t));

	/* Copy out the bios_diskinfo stuff */
	for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
	    dip = TAILQ_NEXT(dip, list))
		bios_diskinfo[i++] = dip->bios_info;

	bios_diskinfo[i++].bios_number = -1;
	/* Register for kernel use */
	addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen);
	addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t),
	    bios_diskinfo);
}

void
cdprobe(void)
{
	struct diskinfo *dip;
	int cddev = bios_cddev & 0xff;

	/* Another BIOS boot device... */

	if (bios_cddev == -1)			/* Not been set, so don't use */
		return;

	dip = alloc(sizeof(struct diskinfo));
	bzero(dip, sizeof(*dip));

#if 0
	if (bios_getdiskinfo(cddev, &dip->bios_info)) {
		printf(" <!cd0>");	/* XXX */
		free(dip, 0);
		return;
	}
#endif

	printf(" cd0");

	dip->bios_info.bios_number = cddev;
	dip->bios_info.bios_edd = 1;		/* Use the LBA calls */
	dip->bios_info.flags |= BDI_GOODLABEL | BDI_EL_TORITO;
	dip->bios_info.checksum = 0;		 /* just in case */
	dip->bios_info.bsd_dev =
	    MAKEBOOTDEV(6, 0, 0, 0, RAW_PART);

	/* Create an imaginary disk label */
	dip->disklabel.d_secsize = 2048;
	dip->disklabel.d_ntracks = 1;
	dip->disklabel.d_nsectors = 100;
	dip->disklabel.d_ncylinders = 1;
	dip->disklabel.d_secpercyl = dip->disklabel.d_ntracks *
	    dip->disklabel.d_nsectors;
	if (dip->disklabel.d_secpercyl == 0) {
		dip->disklabel.d_secpercyl = 100;
		/* as long as it's not 0, since readdisklabel divides by it */
	}

	strncpy(dip->disklabel.d_typename, "ATAPI CD-ROM",
	    sizeof(dip->disklabel.d_typename));
	dip->disklabel.d_type = DTYPE_ATAPI;

	strncpy(dip->disklabel.d_packname, "fictitious",
	    sizeof(dip->disklabel.d_packname));
	DL_SETDSIZE(&dip->disklabel, 100);

	dip->disklabel.d_bbsize = 2048;
	dip->disklabel.d_sbsize = 2048;

	/* 'a' partition covering the "whole" disk */
	DL_SETPOFFSET(&dip->disklabel.d_partitions[0], 0);
	DL_SETPSIZE(&dip->disklabel.d_partitions[0], 100);
	dip->disklabel.d_partitions[0].p_fstype = FS_UNUSED;

	/* The raw partition is special */
	DL_SETPOFFSET(&dip->disklabel.d_partitions[RAW_PART], 0);
	DL_SETPSIZE(&dip->disklabel.d_partitions[RAW_PART], 100);
	dip->disklabel.d_partitions[RAW_PART].p_fstype = FS_UNUSED;

	dip->disklabel.d_npartitions = MAXPARTITIONS;

	dip->disklabel.d_magic = DISKMAGIC;
	dip->disklabel.d_magic2 = DISKMAGIC;
	dip->disklabel.d_checksum = dkcksum(&dip->disklabel);

	/* Add to queue of disks */
	TAILQ_INSERT_TAIL(&disklist, dip, list);
}

/* Find info on given BIOS disk */
struct diskinfo *
dklookup(int dev)
{
	struct diskinfo *dip;

	for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list))
		if (dip->bios_info.bios_number == dev)
			return dip;

	return NULL;
}

void
dump_diskinfo(void)
{
	struct diskinfo *dip;

	printf("Disk\tBIOS#\tType\tCyls\tHeads\tSecs\tFlags\tChecksum\n");
	for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list)) {
		bios_diskinfo_t *bdi = &dip->bios_info;
		int d = bdi->bios_number;
		int u = d & 0x7f;
		char c;

		if (bdi->flags & BDI_EL_TORITO) {
			c = 'c';
			u = 0;
		} else {
		    	c = (d & 0x80) ? 'h' : 'f';
		}

		printf("%cd%d\t0x%x\t%s\t%d\t%d\t%d\t0x%x\t0x%x\n",
		    c, u, d,
		    (bdi->flags & BDI_BADLABEL)?"*none*":"label",
		    bdi->bios_cylinders, bdi->bios_heads, bdi->bios_sectors,
		    bdi->flags, bdi->checksum);
	}
}

/* Find BIOS portion on given BIOS disk
 * XXX - Use dklookup() instead.
 */
bios_diskinfo_t *
bios_dklookup(int dev)
{
	struct diskinfo *dip;

	dip = dklookup(dev);
	if (dip)
		return &dip->bios_info;

	return NULL;
}

/*
 * Checksum one more block on all harddrives
 *
 * Use the adler32() function from libz,
 * as it is quick, small, and available.
 */
int
disksum(int blk)
{
	struct diskinfo *dip, *dip2;
	int st, reprobe = 0;
	char *buf;

	buf = alloca(DEV_BSIZE);
	for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list)) {
		bios_diskinfo_t *bdi = &dip->bios_info;

		/* Skip this disk if it is not a HD or has had an I/O error */
		if (!(bdi->bios_number & 0x80) || bdi->flags & BDI_INVALID)
			continue;

		/* Adler32 checksum */
		st = biosd_io(F_READ, bdi, blk, 1, buf);
		if (st) {
			bdi->flags |= BDI_INVALID;
			continue;
		}
		bdi->checksum = adler32(bdi->checksum, buf, DEV_BSIZE);

		for (dip2 = TAILQ_FIRST(&disklist); dip2 != dip;
				dip2 = TAILQ_NEXT(dip2, list)) {
			bios_diskinfo_t *bd = &dip2->bios_info;
			if ((bd->bios_number & 0x80) &&
			    !(bd->flags & BDI_INVALID) &&
			    bdi->checksum == bd->checksum)
				reprobe = 1;
		}
	}

	return reprobe;
}


code:
/*	$OpenBSD: elf32.c,v 1.1 2007/05/30 01:25:43 tom Exp $	*/

/*
 * Copyright (c) 2007 Tom Cosgrove <tom@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>

#include <sys/param.h>
#include <sys/exec.h>

#include "../../../../lib/libsa/loadfile.h"

#undef ELFSIZE
#define ELFSIZE  32

#include <sys/exec_elf.h>

#include "../../../../lib/libsa/loadfile_elf.c"


code:
/*	$OpenBSD: elf64.c,v 1.1 2007/05/30 01:25:43 tom Exp $	*/

/*
 * Copyright (c) 2007 Tom Cosgrove <tom@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <lib/libkern/libkern.h>
#include <lib/libsa/stand.h>

#include <sys/param.h>
#include <sys/exec.h>

#include "../../../../lib/libsa/loadfile.h"

#undef ELFSIZE
#define ELFSIZE  64

#include <sys/exec_elf.h>

#include "../../../../lib/libsa/loadfile_elf.c"


code:
/*	$OpenBSD: exec_i386.c,v 1.39 2012/11/01 00:55:38 jsing Exp $	*/

/*
 * Copyright (c) 1997-1998 Michael Shalayeff
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <sys/disklabel.h>
#include <dev/cons.h>
#include <lib/libsa/loadfile.h>
#include <machine/biosvar.h>
#include <stand/boot/bootarg.h>

#include "disk.h"
#include "libsa.h"

#ifdef SOFTRAID
#include <dev/softraidvar.h>
#include "softraid.h"
#endif

typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
    __attribute__ ((noreturn));

char *bootmac = NULL;

void
run_loadfile(u_long *marks, int howto)
{
	u_long entry;
#ifndef _TEST
#ifdef EXEC_DEBUG
	extern int debug;
#endif
	dev_t bootdev = bootdev_dip->bootdev;
	size_t ac = BOOTARG_LEN;
	caddr_t av = (caddr_t)BOOTARG_OFF;
	bios_consdev_t cd;
	extern int com_speed; /* from bioscons.c */
	extern int com_addr;
	bios_ddb_t ddb;
	extern int db_console;
	bios_bootduid_t bootduid;
#ifdef SOFTRAID
	bios_bootsr_t bootsr;
	struct sr_boot_volume *bv;
#endif

	if (sa_cleanup != NULL)
		(*sa_cleanup)();

	cd.consdev = cn_tab->cn_dev;
	cd.conspeed = com_speed;
	cd.consaddr = com_addr;
	cd.consfreq = 0;
	addbootarg(BOOTARG_CONSDEV, sizeof(cd), &cd);

	if (bootmac != NULL)
		addbootarg(BOOTARG_BOOTMAC, sizeof(bios_bootmac_t), bootmac);

	if (db_console != -1) {
		ddb.db_console = db_console;
		addbootarg(BOOTARG_DDB, sizeof(ddb), &ddb);
	}

	bcopy(bootdev_dip->disklabel.d_uid, &bootduid.duid, sizeof(bootduid));
	addbootarg(BOOTARG_BOOTDUID, sizeof(bootduid), &bootduid);

#ifdef SOFTRAID
	if (bootdev_dip->sr_vol != NULL) {
		bv = bootdev_dip->sr_vol;
		bzero(&bootsr, sizeof(bootsr));
		bcopy(&bv->sbv_uuid, &bootsr.uuid, sizeof(bootsr.uuid));
		if (bv->sbv_maskkey != NULL)
			bcopy(bv->sbv_maskkey, &bootsr.maskkey,
			    sizeof(bootsr.maskkey));
		addbootarg(BOOTARG_BOOTSR, sizeof(bios_bootsr_t), &bootsr);
		explicit_bzero(&bootsr, sizeof(bootsr));
	}

	sr_clear_keys();
#endif

	/* Pass memory map to the kernel */
	mem_pass();

	makebootargs(av, &ac);

	entry = marks[MARK_ENTRY] & 0x0fffffff;

	printf("entry point at 0x%x\n", (int)entry);

	/* stack and the gung is ok at this point, so, no need for asm setup */
	(*(startfuncp)entry)(howto, bootdev, BOOTARG_APIVER, marks[MARK_END],
	    extmem, cnvmem, ac, (int)av);
	/* not reached */
#endif
}


code:
/*	$OpenBSD: gateA20.c,v 1.10 2004/03/19 13:48:18 tom Exp $	*/

/*
 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
 *
 * Mach Operating System
 * Copyright (c) 1992, 1991 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */

#include <sys/param.h>
#include <sys/types.h>
#include <machine/pio.h>
#include <dev/ic/i8042reg.h>
#include <dev/isa/isareg.h>

#include "libsa.h"

#define KB_A20		0xdf		/* enable A20,
					   enable output buffer full interrupt
					   enable data line
					   enable clock line */

/*
 * "Probe"-style routine (no parameters) to turn A20 on
 */
void
gateA20on(void)
{
	gateA20(1);
}

/*
 * Gate A20 for high memory
 */
void
gateA20(int on)
{
	if (ps2model == 0xf82 ||
	    (inb(IO_KBD + KBSTATP) == 0xff && inb(IO_KBD + KBDATAP) == 0xff)) {
		int data;

		/* Try to use 0x92 to turn on A20 */
		if (on) {
			data = inb(0x92);
			outb(0x92, data | 0x2);
		} else {
			data = inb(0x92);
			outb(0x92, data & ~0x2);
		}
	} else {

		while (inb(IO_KBD + KBSTATP) & KBS_IBF);

		while (inb(IO_KBD + KBSTATP) & KBS_DIB)
			(void)inb(IO_KBD + KBDATAP);

		outb(IO_KBD + KBCMDP, KBC_CMDWOUT);
		while (inb(IO_KBD + KBSTATP) & KBS_IBF);

		if (on)
			outb(IO_KBD + KBDATAP, KB_A20);
		else
			outb(IO_KBD + KBDATAP, 0xcd);
		while (inb(IO_KBD + KBSTATP) & KBS_IBF);

		while (inb(IO_KBD + KBSTATP) & KBS_DIB)
			(void)inb(IO_KBD + KBDATAP);
	}
}


code:
/*	$OpenBSD: gidt.S,v 1.36 2012/10/31 13:55:58 jsing Exp $	*/

/*
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

	.file "gidt.S"

#include <machine/asm.h>
#define _LOCORE
#include <machine/trap.h>
#include <debug_md.h>
#undef _LOCORE
#include <assym.h>

#include "gidt.h"

#ifdef GIDT_DEBUG
#define	gidt_debug0		; \
	mov	$0xb8000, %eax	; \
	mov	$0x47314730, (%eax)
#define	gidt_debug1		; \
	mov	$(0xb8000 - LINKADDR), %eax	; \
	mov	$0x4f314f30, (%eax)
#define	gidt_debug2		; \
	mov	$0xb8004, %eax	; \
	mov	$0x47334732, (%eax)
#define	gidt_debug3		; \
	mov	$0xb8004, %eax	; \
	mov	$0x4f334f32, (%eax)
#define gidt_debug4		; \
	movl	$0xb8008, %eax	; \
	movl	$0x47344733, (%eax)
#else
#define gidt_debug0 /* gidt_debug0 */
#define gidt_debug1 /* gidt_debug1 */
#define gidt_debug2 /* gidt_debug2 */
#define gidt_debug3 /* gidt_debug3 */
#define gidt_debug4 /* gidt_debug4 */
#endif

#define prot2real						\
	gidt_debug0;						\
								\
	ljmp	$S16TEXT, $1f - LINKADDR;			\
1:								\
	.code16;						\
	movw	$S16DATA, %ax;					\
	movw	%ax, %ds;					\
	movw	%ax, %es;					\
	gidt_debug1;						\
								\
	movl	%cr0, %eax;	/* disable pmmm */		\
	andl 	$~CR0_PE, %eax;					\
	movl	%eax, %cr0;					\
								\
	/* reload real cs:ip */					\
	data32 ljmp	$(LINKADDR >> 4), $1f - LINKADDR;	\
1:								\
	movw	%cs, %ax;	/* setup: %ds, %es, %ss = %cs */ \
	movw	%ax, %ds;					\
	movw	%ax, %es;					\
	xorw	%ax, %ax;					\
	movw	%ax, %ss;					\
								\
	gidt_debug2;						\
								\
	data32 addr32 lidt (Idtr_real - LINKADDR); /* load idtr for real mode */

#define real2prot						\
	gidt_debug3;						\
								\
	movw	$LINKADDR >> 4, %ax;				\
	movw	%ax, %ds;					\
	data32 addr32 lgdt (Gdtr - LINKADDR); 	/* load the gdtr */	\
								\
	movl	%cr0, %eax;	/* enable pmmm */		\
	orl	$CR0_PE, %eax;					\
	movl	%eax, %cr0;					\
								\
	data32 ljmp	$S32TEXT, $1f;   /* reload %cs,flush pipeline */\
1:								\
	.code32;						\
	/* reload 32bit %ds, %ss, %es */			\
	mov	$S32DATA, %eax;					\
	mov	%ax, %ds;					\
	mov	%ax, %ss;					\
	mov	%ax, %es;					\
								\
	gidt_debug4;						\
								\
	/* load idtr for debugger and DOS/BIOS iface */		\
	lidt	Idtr;

	.globl	_C_LABEL(BIOS_regs)

	.text
	.code32
	.globl	_ASM_LABEL(pmm_init)
	.globl	_C_LABEL(_rtt)

ENTRY(_rtt)
#ifdef SOFTRAID
	call	_C_LABEL(sr_clear_keys)
#endif
#ifdef GIDT_DEBUG
	movl	$0xb8000, %ebx
	movl	$0x4f514f51, (%ebx)
#endif
	movw	$0x1234, %ax
	movw	%ax, 0x472	/* warm boot */

	/* Try to use the KBD to reboot system */
	movb	$0xfe, %al
	outb	%al, $0x64

	movl	$0x5000, %ecx
1:	inb	$0x84, %al
	loop	1b

	movb	$0xfe, %al
	outb	%al, $0x64

#ifdef GIDT_DEBUG
	movl	$0xb8000, %ebx
	movl	$0x07310731, (%ebx)
#endif

	/* Try to cause a triple fault... */
	lidt	Idtr_reset
	xorl	%eax, %eax
	divl	%eax, %eax

	/* Again... */
	int $0x8

	/* Again... */
	movl	$0, %esp	/* segment violation */
	ret

#define IPROC(n)	X##n
#define IEMU(n)		IPROC(emu##n)

create_idt_entry:
	movw	%ax, (%ebx)
	movw	$S32TEXT, 2(%ebx)
	movw	$((0x80|SDT_SYS386TGT) << 8), 4(%ebx)
	shr	$16, %eax
	movw	%ax, 6(%ebx)
	addl	$8, %ebx
	ret

	.align	8, 0x90
pmm_init:

#define idte(e)	\
	movl $IPROC(e), %eax; call create_idt_entry
#define idtb(b)	idte(emu##b)

	/* Build interrupt descriptor table. */
	/* Maskable interrupts (32-255) */
	movl	$idt, %ebx
	movl	$Idtr, %eax
	movw	$(640 - 1), (%eax)
	movl	%ebx, 2(%eax)

	/* Internal (0-31) */
	idte(de); idte(db); idte(nmi); idte(bp); idte(of); idte(br)
	idte(ud); idte(nm); idte(df);  idte(fo); idte(ts); idte(np)
	idte(ss); idte(gp); idte(pf);  idte(xx); idte(mf); idte(ac)
	idte(mc)
	idte(xx); idte(xx); idte(xx);  idte(xx); idte(xx); idte(xx)
	idte(xx); idte(xx); idte(xx);  idte(xx); idte(xx); idte(xx)
	idte(xx)
	/* BIOS entry points (32-63) */
	idtb(0);  idtb(1);  idtb(2);  idtb(3);  idtb(4);  idtb(5)
	idtb(6);  idtb(7);  idtb(8);  idtb(9);  idtb(10); idtb(11)
	idtb(12); idtb(13); idtb(14); idtb(15); idtb(16); idtb(17)
	idtb(18); idtb(19); idtb(20); idtb(21); idtb(22); idtb(23)
	idtb(24); idtb(25); idtb(26); idtb(27); idtb(28); idtb(29)
	idtb(30); idtb(31); idtb(32); idtb(33); idtb(34); idtb(35)
	idtb(36); idtb(37); idtb(38); idtb(39); idtb(40); idtb(41)
	idtb(42); idtb(43); idtb(44); idtb(45); idtb(46); idtb(47)
	/* DOS entry points (64-80) */

#undef idtb
#undef idte

	/* load idtr for interrupts */
	lidt	Idtr
	ret

	.bss
	.align 8, 0x90
idt:
	/* IDT has 80 entries at 8 bytes each. */
	.space  640

	.globl	Idtr
Idtr:	.word	0  // 640 - 1
	.long	0  // idt
	.word	0

	.text
	.align	8
	.globl	Idtr_real
Idtr_real:
	.word	1023
	.long	0
	.word	0

	.align	8
Idtr_reset:
	.long	0, 0

	.align	8
gdt:
		/* 0x00 : null */
	.space	8
		/* 0x08 : flat code */
	.word	0xFFFF			# lolimit
	.word	0			# lobase
	.byte	0			# midbase
	.byte	SDT_MEMERAC | 0 | 0x80	# RXAC, dpl = 0, present
	.byte	0xf | 0 | 0x40 | 0x80	# hilimit, xx, 32bit, 4k granularity
	.byte	0			# hibase
		/* 0x10 : flat data */
	.word	0xFFFF			# lolimit
	.word	0			# lobase
	.byte	0			# midbase
	.byte	SDT_MEMRWA | 0 | 0x80	# RWA, dpl = 0, present
	.byte	0xf | 0 | 0x40 | 0x80	# hilimit, xx, 32bit, 4k granularity
	.byte	0			# hibase
		/* 0x18 : 16 bit code */
	.word	0xFFFF			# lolimit
	.word	(LINKADDR & 0xffff)	# lobase
	.byte	(LINKADDR >> 16) & 0xff	# midbase
	.byte	SDT_MEMERAC | 0 | 0x80	# RXAC, dpl = 0, present
	.byte	0x0 | 0 | 0 | 0		# hilimit, xx, 16bit, byte granularity
	.byte	(LINKADDR >> 20) & 0xff	# hibase
		/* 0x20 : 16 bit data */
	.word	0xFFFF			# lolimit
	.word	(LINKADDR & 0xffff)	# lobase
	.byte	(LINKADDR >> 16) & 0xff	# midbase
	.byte	SDT_MEMRWA | 0 | 0x80	# RWA, dpl = 0, present
	.byte	0x0 | 0 | 0 | 0		# hilimit, xx, 16bit, byte granularity
	.byte	(LINKADDR >> 20) & 0xff	# hibase

.globl Gdtr
Gdtr:	.word	. - gdt - 1
	.long	gdt
	.word	0

#define IENTRY(name,type) \
IPROC(name): \
	pushl	$type ; \
	jmp	1f
#define IENTRY_ERR(name,err,type) \
IPROC(name): \
	pushl	$err ; \
	pushl	$type ; \
	jmp	1f

IPROC(xx):
	pushl	$1
	pushl	$T_RESERVED
	jmp	1f

IENTRY_ERR(de,0,T_DIVIDE)	/* #DE divide by zero */
IENTRY_ERR(db,0,T_TRCTRAP)	/* #DB debug */
IENTRY_ERR(nmi,0,T_NMI)		/* NMI */
IENTRY_ERR(bp,0,T_BPTFLT)	/* #BP breakpoint */
IENTRY_ERR(of,0,T_OFLOW)	/* #OF overflow */
IENTRY_ERR(br,0,T_BOUND)	/* #BR BOUND range exceeded */
IENTRY_ERR(ud,0,T_PRIVINFLT)	/* #UD invalid opcode */
IENTRY_ERR(nm,0,T_DNA)		/* #NM device not available */
IENTRY(df,T_DOUBLEFLT)		/* #DF double fault */
IENTRY_ERR(fo,0,T_FPOPFLT)	/* #FO coprocessor segment overrun */
IENTRY(ts,T_TSSFLT)		/* #TS invalid TSS */
IENTRY(np,T_SEGNPFLT)		/* #NP segment not present */
IENTRY(ss,T_STKFLT)		/* #SS stack fault */
IENTRY(gp,T_PROTFLT)		/* #GP general protection */
IENTRY(pf,T_PAGEFLT)		/* #PF page fault */
IENTRY_ERR(mf,0,T_ARITHTRAP)	/* #MF floating point error */
IENTRY(ac,T_ALIGNFLT)		/* #AC alignment check */
IENTRY(mc,T_MACHK)		/* #MC machine check */

	.globl	alltraps
1:	/* save on jumps */
	jmp	alltraps

#define	IEMUENT(n)	IEMU(n): pushl $n; jmp 1f

IEMUENT(0);  IEMUENT(1);  IEMUENT(2);  IEMUENT(3)
IEMUENT(4);  IEMUENT(5);  IEMUENT(6);  IEMUENT(7)
IEMUENT(8);  IEMUENT(9);  IEMUENT(10); IEMUENT(11)
IEMUENT(12); IEMUENT(13); IEMUENT(14); IEMUENT(15)
IEMUENT(16); IEMUENT(17); IEMUENT(18); IEMUENT(19)
IEMUENT(20); IEMUENT(21); IEMUENT(22); IEMUENT(23)
IEMUENT(24); IEMUENT(25); IEMUENT(26); IEMUENT(27)
IEMUENT(28); IEMUENT(29); IEMUENT(30); IEMUENT(31)
1:	jmp	EMUh	/* redirect for short jumps */
IEMUENT(32); IEMUENT(33); IEMUENT(34); IEMUENT(35)
IEMUENT(36); IEMUENT(37); IEMUENT(38); IEMUENT(39)
IEMUENT(40); IEMUENT(41); IEMUENT(42); IEMUENT(43)
IEMUENT(44); IEMUENT(45); IEMUENT(46); IEMUENT(47)
1:	jmp	EMUh

/*
 * entry point for BIOS real-mode interface
 * all the magic for real-prot mode switching is here
 *
 * Note: Once in real mode access to .data or .bss should be avoided since it
 * may not be reachable within the current segment. The following code also
 * assumes that .text is writeable.
 *
 * Call:	%eax, %ecx, %edx, %ebx, %ebp, %esi, %edi, %es, %ds
 * Return:	%eax, %edx, %ecx, %eflags (as returned from BIOS)
 *
 */
	.globl	EMUh
	.align	8, 0x90
EMUh:
	/* save %eax */
	mov	%eax, 5f
	pop	%eax

	pusha
	push	%ds
	push	%es
	push	%fs
	push	%gs

	/* save BIOS int vector */
	mov	%al, intno

	/* Load BIOS registers prior to switching to real mode. */
	movl	_C_LABEL(BIOS_regs)+BIOSR_ES, %eax
	mov	%eax, 7f
	movl	_C_LABEL(BIOS_regs)+BIOSR_DS, %eax
	mov	%eax, 6f

	prot2real

	push	%ds

	# data32 movl $Leax, %eax
	.byte	0x66, 0xb8
7:	.long	0x90909090
	mov	%ax, %es

	# data32 movl $Leax, %eax
	.byte	0x66, 0xb8
6:	.long	0x90909090
	mov	%ax, %ds

	# data32 movl $Leax, %eax
	.byte	0x66, 0xb8
5:	.long	0x90909090

	;sti
	int	$0
intno	= . - 1
	;cli

	pop	%ds

	/* Preserve BX and ES for protected mode. */
	addr32 movl %eax, (2f - LINKADDR)
	movl	%ebx, %eax
	addr32 movl %eax, (4f - LINKADDR)
	movl	%es, %eax
	addr32 movl %eax, (3f - LINKADDR)
	addr32 movl (2f - LINKADDR), %eax

	movb	%ah, %bh
	lahf
	xchgb	%ah, %bh

	/* Preserve AX for protected mode. */
	addr32 movl %eax, (2f - LINKADDR)

	real2prot

	# movl $Leax, %eax
	.byte	0xb8
4:	.long	0x90909090
	movl	%eax, _C_LABEL(BIOS_regs)+BIOSR_BX

	# movl $Leax, %eax
	.byte	0xb8
3:	.long	0x90909090
	movl	%eax, _C_LABEL(BIOS_regs)+BIOSR_ES

	# movl $Leax, %eax
	.byte	0xb8
2:	.long	0x90909090

	/* pass BIOS return values back to caller */
	movl	%eax, 0xb*4(%esp)
	movl	%ecx, 0xa*4(%esp)
	movl	%edx, 0x9*4(%esp)
	movb	%bh , 0xe*4(%esp)

	/* clear NT flag in eflags */
	/* Martin Fredriksson <martin@gbg.netman.se> */
	pushf
	pop	%eax
	and	$0xffffbfff, %eax
	push	%eax
	popf

	/* save registers into save area */
	movl	%eax, _C_LABEL(BIOS_regs)+BIOSR_AX
	movl	%ecx, _C_LABEL(BIOS_regs)+BIOSR_CX
	movl	%edx, _C_LABEL(BIOS_regs)+BIOSR_DX
	movl	%ebp, _C_LABEL(BIOS_regs)+BIOSR_BP
	movl	%esi, _C_LABEL(BIOS_regs)+BIOSR_SI
	movl	%edi, _C_LABEL(BIOS_regs)+BIOSR_DI

	pop	%gs
	pop	%fs
	pop	%es
	pop	%ds
	popa
	iret

/* Call buffer at 07c0:0000 in real mode to simulate a BIOS boot */
ENTRY(bootbuf)
	pop	%eax		/* Don't need return address */
	pop	%esi		/* Buffer */
	pop	%edx		/* Device */
	prot2real		/* Switch */

	/* Set up stack */
	cli
	xor	%ax, %ax
	mov	%ax, %ss
	mov	$0xfffc, %esp
	sti

	/* Jump to buffer */
	ljmp	$0x0, $0x7c00

	.end


code:
/*	$OpenBSD: gidt.h,v 1.1 2004/03/19 13:48:18 tom Exp $	*/

/*
 * Copyright (c) 2004 Tom Cosgrove
 * Copyright (c) 1997 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#define	SNULL	0x00
#define S32TEXT	0x08
#define	S32DATA	0x10
#define S16TEXT	0x18
#define	S16DATA	0x20


code:
/*	$OpenBSD: libsa.h,v 1.45 2010/07/02 00:36:52 weingart Exp $	*/

/*
 * Copyright (c) 1996-1999 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <lib/libsa/stand.h>
#include <machine/biosvar.h>

#define	EXEC_ELF

#define	DEFAULT_KERNEL_ADDRESS	0

struct i386_boot_probes {
	char *name;
	void (**probes)(void);
	int count;
};

extern void (*sa_cleanup)(void);

void gateA20(int);
void gateA20on(void);

void cpuprobe(void);
void smpprobe(void);
void ps2probe(void);
void pciprobe(void);
void memprobe(void);
void diskprobe(void);
void cdprobe(void);
void apmprobe(void);
void apmfixmem(void);
void dump_biosmem(bios_memmap_t *);
int mem_add(long long, long long);
int mem_delete(long long, long long);
int mem_limit(long long);
void mem_pass(void);

void devboot(dev_t, char *);
void machdep(void);

void *getSYSCONFaddr(void);
void *getEBDAaddr(void);

extern const char bdevs[][4];
extern const int nbdevs;
extern u_int cnvmem, extmem; /* XXX global pass memprobe()->machdep_start() */
extern int ps2model;

extern struct i386_boot_probes probe_list[];
extern int nibprobes;
extern void (*devboot_p)(dev_t, char *);

/* diskprobe.c */
extern bios_diskinfo_t bios_diskinfo[];
extern u_int32_t bios_cksumlen;

#define MACHINE_CMD	cmd_machine /* we have i386-specific commands */

#define CHECK_SKIP_CONF	check_skip_conf	/* we can skip boot.conf with Ctrl */


code:
/*	$OpenBSD: machdep.c,v 1.36 2007/04/27 10:08:34 tom Exp $	*/

/*
 * Copyright (c) 2004 Tom Cosgrove
 * Copyright (c) 1997-1999 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "libsa.h"
#include "biosdev.h"
#include <machine/apmvar.h>
#include <machine/biosvar.h>

volatile struct BIOS_regs	BIOS_regs;

#if defined(DEBUG) && !defined(_TEST)
#define CKPT(c)	(*(u_int16_t*)0xb8148 = 0x4700 + (c))
#else
#define CKPT(c) /* c */
#endif

void
machdep(void)
{
	int i, j;
	struct i386_boot_probes *pr;

	/*
	 * The list of probe routines is now in conf.c.
	 */
	for (i = 0; i < nibprobes; i++) {
		pr = &probe_list[i];
		if (pr != NULL) {
			printf("%s:", pr->name);

			for (j = 0; j < pr->count; j++) {
				(*(pr->probes)[j])();
			}

			printf("\n");
		}
	}
}

int check_skip_conf(void)
{
	/* Return non-zero (skip boot.conf) if Control "shift" key down */
	return (pc_getshifts(0) & 0x04);
}


code:
/*	$OpenBSD: memprobe.c,v 1.53 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 1997-1999 Michael Shalayeff
 * Copyright (c) 1997-1999 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <machine/biosvar.h>
#include <dev/isa/isareg.h>
#include <stand/boot/bootarg.h>
#include "libsa.h"

u_int cnvmem, extmem;		/* XXX - compatibility */

/*
 * Check gateA20
 *
 * A sanity check.
 */
static __inline int
checkA20(void)
{
	register char *p = (char *)0x100000;
	register char *q = (char *)0x000000;
	int st;

	/* Simple check */
	if (*p != *q)
		return 1;

	/* Complex check */
	*p = ~(*p);
	st = (*p != *q);
	*p = ~(*p);

	return st;
}

/*
 * BIOS int 15, AX=E820
 *
 * This is the "preferred" method.
 */
static __inline bios_memmap_t *
bios_E820(bios_memmap_t *mp)
{
	int rc, off = 0, sig, gotcha = 0;

	do {
		BIOS_regs.biosr_es = ((u_int)(mp) >> 4);
		__asm volatile(DOINT(0x15) "; setc %b1"
		    : "=a" (sig), "=d" (rc), "=b" (off)
		    : "0" (0xE820), "1" (0x534d4150), "b" (off),
		      "c" (sizeof(*mp)), "D" (((u_int)mp) & 0xf)
		    : "cc", "memory");
		off = BIOS_regs.biosr_bx;

		if (rc & 0xff || sig != 0x534d4150)
			break;
		gotcha++;
		if (!mp->type)
			mp->type = BIOS_MAP_RES;
		mp++;
	} while (off);

	if (!gotcha)
		return NULL;
#ifdef DEBUG
	printf("0x15[E820] ");
#endif
	return mp;
}

#if 0
/*
 * BIOS int 15, AX=E801
 *
 * Only used if int 15, AX=E820 does not work.
 * This should work for more than 64MB on most
 * modern machines.  However, there is always
 * an exception, the older IBM machine do not
 * like this call.
 */
static __inline bios_memmap_t *
bios_E801(bios_memmap_t *mp)
{
	int rc, m1, m2, m3, m4;
	u_int8_t *info;

	/* Test for possibility of 0xE801 */
	info =  getSYSCONFaddr();
	if (!info)
		return NULL;
	/* XXX - Should test model/submodel/rev here */
	printf("model(%d,%d,%d)", info[2], info[3], info[4]);

	/* Check for 94 or later bios */
	info = (void *)0xFFFFB;
	if (info[0] == '9' && info[1] <= '3')
		return NULL;

	/* We might have this call */
	__asm volatile(DOINT(0x15) "; mov %%ax, %%si; setc %b0"
	    : "=a" (rc), "=S" (m1), "=b" (m2), "=c" (m3), "=d" (m4)
	    : "0" (0xE801));

	/* Test for failure */
	if (rc & 0xff)
		return NULL;

	/* Fixup for screwed up machines */
	if (m1 == 0) {
		m1 = m3;
		m2 = m4;
	}
#ifdef DEBUG
	printf("0x15[E801] ");
#endif
	/* Fill out BIOS map */
	mp->addr = (1024 * 1024);	/* 1MB */
	mp->size = (m1 & 0xffff) * 1024;
	mp->type = BIOS_MAP_FREE;

	mp++;
	mp->addr = (1024 * 1024) * 16;	/* 16MB */
	mp->size = (m2 & 0xffff) * 64L * 1024;
	mp->type = BIOS_MAP_FREE;

	return ++mp;
}
#endif

/*
 * BIOS int 15, AX=8800
 *
 * Only used if int 15, AX=E801 does not work.
 * Machines with this are restricted to 64MB.
 */
static __inline bios_memmap_t *
bios_8800(bios_memmap_t *mp)
{
	int rc, mem;

	__asm volatile(DOINT(0x15) "; setc %b0"
	    : "=c" (rc), "=a" (mem) : "a" (0x8800));

	if (rc & 0xff)
		return NULL;
#ifdef DEBUG
	printf("0x15[8800] ");
#endif
	/* Fill out a BIOS_MAP */
	mp->addr = 1024 * 1024;		/* 1MB */
	mp->size = (mem & 0xffff) * 1024;
	mp->type = BIOS_MAP_FREE;

	return ++mp;
}

/*
 * BIOS int 0x12 Get Conventional Memory
 *
 * Only used if int 15, AX=E820 does not work.
 */
static __inline bios_memmap_t *
bios_int12(bios_memmap_t *mp)
{
	int mem;
#ifdef DEBUG
	printf("0x12 ");
#endif
	__asm volatile(DOINT(0x12) : "=a" (mem) :: "%ecx", "%edx", "cc");

	/* Fill out a bios_memmap_t */
	mp->addr = 0;
	mp->size = (mem & 0xffff) * 1024;
	mp->type = BIOS_MAP_FREE;

	return ++mp;
}

/*
 * addrprobe(kloc): Probe memory at address kloc * 1024.
 *
 * This is a hack, but it seems to work ok.  Maybe this is
 * the *real* way that you are supposed to do probing???
 *
 * Modify the original a bit.  We write everything first, and
 * then test for the values.  This should croak on machines that
 * return values just written on non-existent memory...
 *
 * BTW: These machines are pretty broken IMHO.
 *
 * XXX - Does not detect aliased memory.
 */
const u_int addrprobe_pat[] = {
	0x00000000, 0xFFFFFFFF,
	0x01010101, 0x10101010,
	0x55555555, 0xCCCCCCCC
};
static int
addrprobe(u_int kloc)
{
	volatile u_int *loc;
	register u_int i, ret = 0;
	u_int save[nitems(addrprobe_pat)];

	/* Get location */
	loc = (int *)(kloc * 1024);

	save[0] = *loc;
	/* Probe address */
	for (i = 0; i < nitems(addrprobe_pat); i++) {
		*loc = addrprobe_pat[i];
		if (*loc != addrprobe_pat[i])
			ret++;
	}
	*loc = save[0];

	if (!ret) {
		/* Write address */
		for (i = 0; i < nitems(addrprobe_pat); i++) {
			save[i] = loc[i];
			loc[i] = addrprobe_pat[i];
		}

		/* Read address */
		for (i = 0; i < nitems(addrprobe_pat); i++) {
			if (loc[i] != addrprobe_pat[i])
				ret++;
			loc[i] = save[i];
		}
	}

	return ret;
}

/*
 * Probe for all extended memory.
 *
 * This is only used as a last resort.  If we resort to this
 * routine, we are getting pretty desperate.  Hopefully nobody
 * has to rely on this after all the work above.
 *
 * XXX - Does not detect aliased memory.
 * XXX - Could be destructive, as it does write.
 */
static __inline bios_memmap_t *
badprobe(bios_memmap_t *mp)
{
	u_int64_t ram;
#ifdef DEBUG
	printf("scan ");
#endif
	/*
	 * probe extended memory
	 *
	 * There is no need to do this in assembly language.  This is
	 * much easier to debug in C anyways.
	 */
	for (ram = 1024; ram < 512 * 1024; ram += 4)
		if (addrprobe(ram))
			break;

	mp->addr = 1024 * 1024;
	mp->size = (ram - 1024) * 1024;
	mp->type = BIOS_MAP_FREE;

	return ++mp;
}

bios_memmap_t bios_memmap[64];	/* This is easier */
#ifndef _TEST
void
memprobe(void)
{
	bios_memmap_t *pm = bios_memmap, *im;

#ifdef DEBUG
	printf(" mem(");
#else
	printf(" mem[");
#endif

	if ((pm = bios_E820(bios_memmap)) == NULL) {
		im = bios_int12(bios_memmap);
#if 0
		pm = bios_E801(im);
		if (pm == NULL)
#endif
			pm = bios_8800(im);
		if (pm == NULL)
			pm = badprobe(im);
		if (pm == NULL) {
			printf(" No Extended memory detected.");
			pm = im;
		}
	}
	pm->type = BIOS_MAP_END;

	/* XXX - gotta peephole optimize the list */

	/* Remove APM needed RAM */
	apmfixmem();

#ifdef DEBUG
	printf(")[");
#endif

	/* XXX - Compatibility, remove later (smpprobe() relies on it) */
	extmem = cnvmem = 0;
	for (im = bios_memmap; im->type != BIOS_MAP_END; im++) {
		/* Count only "good" memory chunks 12K and up in size */
		if ((im->type == BIOS_MAP_FREE) && (im->size >= 12 * 1024)) {
			if (im->size > 1024 * 1024)
				printf("%uM ", (u_int)(im->size /
				    (1024 * 1024)));
			else
				printf("%uK ", (u_int)im->size / 1024);

			/*
			 * Compute compatibility values:
			 * cnvmem -- is the upper boundary of conventional
			 *	memory (below IOM_BEGIN (=640k))
			 * extmem -- is the size of the contignous extended
			 *	memory segment starting at 1M
			 *
			 * We ignore "good" memory in the 640K-1M hole.
			 * We drop "machine {cnvmem,extmem}" commands.
			 */
			if (im->addr < IOM_BEGIN)
				cnvmem = max(cnvmem,
				    im->addr + im->size) / 1024;
			if (im->addr >= IOM_END)
				extmem += im->size / 1024;
		}
	}

	/* Check if gate A20 is on */
	printf("a20=o%s] ", checkA20()? "n" : "ff!");
}
#endif

void
dump_biosmem(bios_memmap_t *tm)
{
	register bios_memmap_t *p;
	register u_int total = 0;

	if (tm == NULL)
		tm = bios_memmap;

	for (p = tm; p->type != BIOS_MAP_END; p++) {
		printf("Region %ld: type %u at 0x%llx for %uKB\n",
		    (long)(p - tm), p->type, p->addr,
		    (u_int)(p->size / 1024));

		if (p->type == BIOS_MAP_FREE)
			total += p->size / 1024;
	}

	printf("Low ram: %dKB  High ram: %dKB\n", cnvmem, extmem);
	printf("Total free memory: %uKB\n", total);
}

int
mem_limit(long long ml)
{
	register bios_memmap_t *p;

	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
		register int64_t sp = p->addr, ep = p->addr + p->size;

		if (p->type != BIOS_MAP_FREE)
			continue;

		/* Wholy above limit, nuke it */
		if ((sp >= ml) && (ep >= ml)) {
			bcopy (p + 1, p, (char *)bios_memmap +
			       sizeof(bios_memmap) - (char *)p);
		} else if ((sp < ml) && (ep >= ml)) {
			p->size -= (ep - ml);
		}
	}
	return 0;
}

int
mem_delete(long long sa, long long ea)
{
	register bios_memmap_t *p;

	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
		if (p->type == BIOS_MAP_FREE) {
			register int64_t sp = p->addr, ep = p->addr + p->size;

			/* can we eat it as a whole? */
			if ((sa - sp) <= PAGE_SIZE && (ep - ea) <= PAGE_SIZE) {
				bcopy(p + 1, p, (char *)bios_memmap +
				    sizeof(bios_memmap) - (char *)p);
				break;
			/* eat head or legs */
			} else if (sa <= sp && sp < ea) {
				p->addr = ea;
				p->size = ep - ea;
				break;
			} else if (sa < ep && ep <= ea) {
				p->size = sa - sp;
				break;
			} else if (sp < sa && ea < ep) {
				/* bite in half */
				bcopy(p, p + 1, (char *)bios_memmap +
				    sizeof(bios_memmap) - (char *)p -
				    sizeof(bios_memmap[0]));
				p[1].addr = ea;
				p[1].size = ep - ea;
				p->size = sa - sp;
				break;
			}
		}
	}
	return 0;
}

int
mem_add(long long sa, long long ea)
{
	register bios_memmap_t *p;

	for (p = bios_memmap; p->type != BIOS_MAP_END; p++) {
		if (p->type == BIOS_MAP_FREE) {
			register int64_t sp = p->addr, ep = p->addr + p->size;

			/* is it already there? */
			if (sp <= sa && ea <= ep) {
				break;
			/* join head or legs */
			} else if (sa < sp && sp <= ea) {
				p->addr = sa;
				p->size = ep - sa;
				break;
			} else if (sa <= ep && ep < ea) {
				p->size = ea - sp;
				break;
			} else if (ea < sp) {
				/* insert before */
				bcopy(p, p + 1, (char *)bios_memmap +
				    sizeof(bios_memmap) - (char *)(p - 1));
				p->addr = sa;
				p->size = ea - sa;
				break;
			}
		}
	}

	/* meaning add new item at the end of the list */
	if (p->type == BIOS_MAP_END) {
		p[1] = p[0];
		p->type = BIOS_MAP_FREE;
		p->addr = sa;
		p->size = ea - sa;
	}

	return 0;
}

void
mem_pass(void)
{
	bios_memmap_t *p;

	for (p = bios_memmap; p->type != BIOS_MAP_END; p++)
		;
	addbootarg(BOOTARG_MEMMAP, (p - bios_memmap + 1) * sizeof *bios_memmap,
	    bios_memmap);
}


code:
/*	$OpenBSD: pciprobe.c,v 1.10 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 1997 Tobias Weingartner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <sys/param.h>
#include <stand/boot/bootarg.h>
#include <machine/biosvar.h>
#include "libsa.h"

#define PCI_SIG 0x20494350		/* PCI Signature */

void
pciprobe(void)
{
	bios_pciinfo_t bpi;
	u_int32_t hw_chars, rev, rc, sig;
	u_int32_t entry32;

	/* PCI BIOS v2.0c+ - Installation Check */
	__asm volatile(DOINT(0x1A) "; shll $8,%2; setc %b2"
		: "=a" (hw_chars), "=b" (rev), "=c" (rc),
		  "=d" (sig), "=D" (entry32)
		: "0" (0xB101), "4" (0x0)
		: "cc");

	if (rc & 0xff || hw_chars & 0xff00)
		return;
	if (sig != PCI_SIG)
		return;

	printf(" pci");
#ifdef DEBUG
	printf("[V%d.%d, %x 0x%x %d]", (rev>>8)&0xFF, (rev&0xFF),
		hw_chars, entry32, (rc>>8)&0xFF);
#endif

	bpi.pci_chars = hw_chars & 0xFFFF;
	bpi.pci_rev = rev & 0xFFFF;
	bpi.pci_entry32 = entry32;
	bpi.pci_lastbus = (rc>>8) & 0xFF;

	addbootarg(BOOTARG_PCIINFO, sizeof(bios_pciinfo_t), &bpi);
}


code:
/*	$OpenBSD: ps2probe.c,v 1.2 2014/03/29 18:09:29 guenther Exp $	*/

/*
 * Copyright (c) 2001 Michael Shalayeff
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "libsa.h"

int ps2model;

void
ps2probe(void)
{
	char *p;
	int r;

	__asm volatile(DOINT(0x15) "\n\t"
			 "setc %b0\n\t"
			 : "=a" (r), "=b" (p)
			 : "0" (0xc000)
			 : "%ecx", "cc");
	if (!(r & 0xff))
		ps2model = (p[2] << 8) | p[3];
}


code:
/*	$OpenBSD: pxe.c,v 1.6 2014/08/21 14:24:08 mpi Exp $ */
/*	$NetBSD: pxe.c,v 1.5 2003/03/11 18:29:00 drochner Exp $	*/

/*
 * Copyright 2001 Wasabi Systems, Inc.
 * All rights reserved.
 *
 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed for the NetBSD Project by
 *	Wasabi Systems, Inc.
 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
 *    or promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org>
 * All rights reserved.
 * Copyright (c) 2000 Paul Saab <ps@freebsd.org>
 * All rights reserved.
 * Copyright (c) 2000 John Baldwin <jhb@freebsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Support for the Intel Preboot Execution Environment (PXE).
 *
 * PXE provides a UDP implementation as well as a UNDI network device
 * driver.  UNDI is much more complicated to use than PXE UDP, so we
 * use PXE UDP as a cheap and easy way to get PXE support.
 */

#include <sys/param.h>
#include <sys/socket.h>

#ifdef _STANDALONE
#include <lib/libkern/libkern.h>
#else
#include <string.h>
#endif

#include <net/if.h>

#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>

#include <lib/libsa/stand.h>
#include <lib/libsa/net.h>
#include <lib/libsa/bootp.h>

#include <stand/boot/bootarg.h>
#include <machine/biosvar.h>

#include "pxeboot.h"
#include "pxe.h"
#include "pxe_netif.h"

void	(*pxe_call)(u_int16_t);

void	pxecall_bangpxe(u_int16_t);	/* pxe_call.S */
void	pxecall_pxenv(u_int16_t);	/* pxe_call.S */

char pxe_command_buf[256];

BOOTPLAYER bootplayer;

struct in_addr servip;			/* for tftp */	/* XXX init this */

extern char *bootmac;			/* To pass to kernel */

/* static struct btinfo_netif bi_netif; */

/*****************************************************************************
 * This section is a replacement for libsa/udp.c
 *****************************************************************************/

/* Caller must leave room for ethernet, ip, and udp headers in front!! */
ssize_t
pxesendudp(struct iodesc *d, void *pkt, size_t len)
{
	t_PXENV_UDP_WRITE *uw = (void *) pxe_command_buf;

	uw->status = 0;

	uw->ip = d->destip.s_addr;
	uw->gw = gateip.s_addr;
	uw->src_port = d->myport;
	uw->dst_port = d->destport;
	uw->buffer_size = len;
	uw->buffer.segment = VTOPSEG(pkt);
	uw->buffer.offset = VTOPOFF(pkt);

	pxe_call(PXENV_UDP_WRITE);

	if (uw->status != PXENV_STATUS_SUCCESS) {
		/* XXX This happens a lot; it shouldn't. */
		if (uw->status != PXENV_STATUS_FAILURE)
			printf("sendudp: PXENV_UDP_WRITE failed: 0x%x\n",
			    uw->status);
		return -1;
	}

	return len;
}

/*
 * Receive a UDP packet and validate it for us.
 * Caller leaves room for the headers (Ether, IP, UDP).
 */
ssize_t
pxereadudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
{
	t_PXENV_UDP_READ *ur = (void *) pxe_command_buf;
	struct udphdr *uh;
	struct ip *ip;

	uh = (struct udphdr *)pkt - 1;
	ip = (struct ip *)uh - 1;

	bzero(ur, sizeof(*ur));

	ur->dest_ip = d->myip.s_addr;
	ur->d_port = d->myport;
	ur->buffer_size = len;
	ur->buffer.segment = VTOPSEG(pkt);
	ur->buffer.offset = VTOPOFF(pkt);

	/* XXX Timeout unused. */

	pxe_call(PXENV_UDP_READ);

	if (ur->status != PXENV_STATUS_SUCCESS) {
		/* XXX This happens a lot; it shouldn't. */
		if (ur->status != PXENV_STATUS_FAILURE)
			printf("readudp: PXENV_UDP_READ_failed: 0x%0x\n",
			    ur->status);
		return -1;
	}

	ip->ip_src.s_addr = ur->src_ip;
	uh->uh_sport = ur->s_port;
	uh->uh_dport = d->myport;

	return ur->buffer_size;
}

/*
 * netif layer:
 *  open, close, shutdown: called from dev_net.c
 *  socktodesc: called by network protocol modules
 *
 * We only allow one open socket.
 */

static int pxe_inited;
static struct iodesc desc;

int
pxe_netif_open()
{
	t_PXENV_UDP_OPEN *uo = (void *) pxe_command_buf;

#ifdef NETIF_DEBUG
	printf("pxe_netif_open()\n");
#endif
	if (!pxe_inited) {
		if (pxe_init(0) != 0)
			return -1;
		pxe_inited = 1;
	}
	/* BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); */

	bzero(uo, sizeof(*uo));

	uo->src_ip = bootplayer.yip;

	pxe_call(PXENV_UDP_OPEN);

	if (uo->status != PXENV_STATUS_SUCCESS) {
		printf("\npxe_netif_open: PXENV_UDP_OPEN failed: 0x%x\n",
		    uo->status);
		return -1;
	}

	bcopy(bootplayer.CAddr, desc.myea, ETHER_ADDR_LEN);
	bootmac = bootplayer.CAddr;

	/*
	 * Since the PXE BIOS has already done DHCP, make sure we
	 * don't reuse any of its transaction IDs.
	 */
	desc.xid = bootplayer.ident;

	return 0;
}

void
pxe_netif_close(sock)
	int sock;
{
	t_PXENV_UDP_CLOSE *uc = (void *) pxe_command_buf;

#ifdef NETIF_DEBUG
	if (sock != 0)
		printf("pxe_netif_close: sock=%d\n", sock);
#endif

	uc->status = 0;

	pxe_call(PXENV_UDP_CLOSE);

	if (uc->status != PXENV_STATUS_SUCCESS)
		printf("pxe_netif_end: PXENV_UDP_CLOSE failed: 0x%x\n",
		    uc->status);
}

void
pxe_netif_shutdown()
{
#ifdef NETIF_DEBUG
	printf("pxe_netif_shutdown()\n");
#endif

	pxe_shutdown();
}

struct iodesc *
pxesocktodesc(sock)
	int sock;
{

#ifdef NETIF_DEBUG
	if (sock != 0)
		return 0;
	else
#endif
		return &desc;
}

/*****************************************************************************
 * PXE initialization and support routines
 *****************************************************************************/

u_int16_t pxe_command_buf_seg;
u_int16_t pxe_command_buf_off;

extern u_int16_t bangpxe_off, bangpxe_seg;
extern u_int16_t pxenv_off, pxenv_seg;

/* static struct btinfo_netif bi_netif; */

void
pxeprobe(void)
{
	if (!pxe_inited) {
		if (pxe_init(1) == 0) {
			pxe_inited = 1;
		}
	}
}

int
pxe_init(int quiet)
{
	t_PXENV_GET_CACHED_INFO *gci = (void *) pxe_command_buf;
	pxenv_t *pxenv;
	pxe_t *pxe;
	char *cp;
	int i;
	u_int8_t cksum, *ucp;

	/*
	 * Checking for the presence of PXE is a machine-dependent
	 * operation.  On the IA-32, this can be done two ways:
	 *
	 *	Int 0x1a function 0x5650
	 *
	 *	Scan memory for the !PXE or PXENV+ signatures
	 *
	 * We do the latter, since the Int method returns a pointer
	 * to a deprecated structure (PXENV+).
	 */

	pxenv = NULL;
	pxe = NULL;

	for (cp = (char *)0xa0000; cp > (char *)0x10000; cp -= 2) {
		if (pxenv == NULL) {
			pxenv = (pxenv_t *)cp;
			if (memcmp(pxenv->Signature, S_SIZE("PXENV+")) != 0)
				pxenv = NULL;
			else {
				for (i = 0, ucp = (u_int8_t *)cp, cksum = 0;
				     i < pxenv->Length; i++)
					cksum += ucp[i];
				if (cksum != 0) {
					printf("\npxe_init: bad cksum (0x%x) "
					    "for PXENV+ at 0x%lx\n", cksum,
					    (u_long) cp);
					pxenv = NULL;
				}
			}
		}

		if (pxe == NULL) {
			pxe = (pxe_t *)cp;
			if (memcmp(pxe->Signature, S_SIZE("!PXE")) != 0)
				pxe = NULL;
			else {
				for (i = 0, ucp = (u_int8_t *)cp, cksum = 0;
				     i < pxe->StructLength; i++)
					cksum += ucp[i];
				if (cksum != 0) {
					printf("pxe_init: bad cksum (0x%x) "
					    "for !PXE at 0x%lx\n", cksum,
					    (u_long) cp);
					pxe = NULL;
				}
			}
		}

		if (pxe != NULL && pxenv != NULL)
			break;
	}

	if (pxe == NULL && pxenv == NULL) {
		if (!quiet) printf("pxe_init: No PXE BIOS found.\n");
		return 1;
	}

	if (pxenv == NULL) {
		/* assert(pxe != NULL); */

		printf(quiet ? " pxe!" : "PXE present\n");
	} else {				/* pxenv != NULL */
		int bang = 0;

		if (pxenv->Version >= 0x0201 && pxe != NULL) {
			/* 2.1 or greater -- don't use PXENV+ */
			bang = 1;
		}

		if (quiet) {
			printf(" pxe%c[%d.%d]",
			    (bang ? '!' : '+'),
			    (pxenv->Version >> 8) & 0xff,
			     pxenv->Version & 0xff);
		} else {
			printf("PXE BIOS Version %d.%d\n",
			    (pxenv->Version >> 8) & 0xff,
			     pxenv->Version & 0xff);
		}

		if (bang) {
			pxenv = NULL;
		}
	}

	if (pxenv == NULL) {
		pxe_call = pxecall_bangpxe;
		bangpxe_off = pxe->EntryPointSP.offset;
		bangpxe_seg = pxe->EntryPointSP.segment;
	} else {
		pxe_call = pxecall_pxenv;
		pxenv_off = pxenv->RMEntry.offset;
		pxenv_seg = pxenv->RMEntry.segment;
	}

	/*
	 * Pre-compute the segment/offset of the pxe_command_buf
	 * to make things nicer in the low-level calling glue.
	 */
	pxe_command_buf_seg = VTOPSEG(pxe_command_buf);
	pxe_command_buf_off = VTOPOFF(pxe_command_buf);

	/*
	 * Get the cached info from the server's Discovery reply packet.
	 */
	bzero(gci, sizeof(*gci));
	gci->PacketType = PXENV_PACKET_TYPE_CACHED_REPLY;
	pxe_call(PXENV_GET_CACHED_INFO);

	if (gci->Status != PXENV_STATUS_SUCCESS) {
		printf("\npxeinfo: PXENV_GET_CACHED_INFO failed: 0x%x\n",
		    gci->Status);
		return 1;
	}

	memcpy(&bootplayer,
	    SEGOFF2FLAT(gci->Buffer.segment, gci->Buffer.offset),
	    gci->BufferSize);

	bcopy(&bootplayer.yip, &myip.s_addr, sizeof(myip.s_addr));
	bcopy(&bootplayer.sip, &servip.s_addr, sizeof(servip.s_addr));

        /* Compute our "natural" netmask. */
	if (IN_CLASSA(myip.s_addr))
		netmask = IN_CLASSA_NET;
	else if (IN_CLASSB(myip.s_addr))
		netmask = IN_CLASSB_NET;
	else
		netmask = IN_CLASSC_NET;

	return 0;
}

void
pxeinfo(void)
{
	u_int8_t *p;
#ifdef PXE_DEBUG
	t_PXENV_UNDI_GET_NIC_TYPE *gnt = (void *) pxe_command_buf;
#endif

	printf(" mac %s", ether_sprintf(bootplayer.CAddr));
	p = (u_int8_t *)&myip.s_addr;
	printf(", ip %d.%d.%d.%d", p[0], p[1], p[2], p[3]);
	p = (u_int8_t *)&servip.s_addr;
	printf(", server %d.%d.%d.%d", p[0], p[1], p[2], p[3]);

#ifdef PXE_DEBUG
	/*
	 * Get network interface information.
	 */
	bzero(gnt, sizeof(*gnt));
	pxe_call(PXENV_UNDI_GET_NIC_TYPE);

	if (gnt->Status != PXENV_STATUS_SUCCESS) {
		printf("\npxeinfo: PXENV_UNDI_GET_NIC_TYPE failed: 0x%x\n",
		    gnt->Status);
		return;
	}

	switch (gnt->NicType) {
	case PCI_NIC:
	case CardBus_NIC:
		/* strncpy(bi_netif.ifname, "pxe", sizeof(bi_netif.ifname)); */
		/* bi_netif.bus = BI_BUS_PCI; */
		/* bi_netif.addr.tag = gnt->info.pci.BusDevFunc; */

		printf("\nPXE: Using %s device at bus %d device %d function %d\n",
		    gnt->NicType == PCI_NIC ? "PCI" : "CardBus",
		    (gnt->info.pci.BusDevFunc >> 8) & 0xff,
		    (gnt->info.pci.BusDevFunc >> 3) & 0x1f,
		    gnt->info.pci.BusDevFunc & 0x7);
		break;

	case PnP_NIC:
		/* XXX Make bootinfo work with this. */
		printf("\nPXE: Using PnP device at 0x%x\n",
		    gnt->info.pnp.CardSelNum);
	}
#endif
}

void
pxe_shutdown(void)
{
	int try;
	t_PXENV_UNLOAD_STACK *unload = (void *) pxe_command_buf;
	t_PXENV_UNDI_SHUTDOWN *shutdown = (void *) pxe_command_buf;
#ifdef PXE_DEBUG
	t_PXENV_UDP_CLOSE *close = (void *) pxe_command_buf;
#endif

	if (pxe_call == NULL)
		return;

	/* Close any open UDP connections.  Ignore return value. */
	pxe_call(PXENV_UDP_CLOSE);
#ifdef PXE_DEBUG
	printf("pxe_shutdown: PXENV_UDP_CLOSE returned 0x%x\n", close->status);
#endif

	/* Sometimes PXENV_UNDI_SHUTDOWN doesn't work at first */
	for (try = 3; try > 0; try--) {
		pxe_call(PXENV_UNDI_SHUTDOWN);

		if (shutdown->Status == PXENV_STATUS_SUCCESS)
			break;

		printf("pxe_shutdown: PXENV_UNDI_SHUTDOWN failed: 0x%x\n",
		    shutdown->Status);

		if (try != 1)
			sleep(1);
	}

	/* Have multiple attempts at PXENV_UNLOAD_STACK, too */
	for (try = 3; try > 0; try--) {
		pxe_call(PXENV_UNLOAD_STACK);

		if (unload->Status == PXENV_STATUS_SUCCESS)
			break;

		printf("pxe_shutdown: PXENV_UNLOAD_STACK failed: 0x%x\n",
		    unload->Status);

		if (try != 1)
			sleep(1);
	}
}