summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/i386/boot/cdboot/Makefile114
-rw-r--r--sys/i386/boot/cdboot/asm.S278
-rw-r--r--sys/i386/boot/cdboot/bios.S411
-rw-r--r--sys/i386/boot/cdboot/boot.c393
-rw-r--r--sys/i386/boot/cdboot/boot.h180
-rw-r--r--sys/i386/boot/cdboot/cdrom.c356
-rw-r--r--sys/i386/boot/cdboot/io.c287
-rw-r--r--sys/i386/boot/cdboot/malloc.c179
8 files changed, 2198 insertions, 0 deletions
diff --git a/sys/i386/boot/cdboot/Makefile b/sys/i386/boot/cdboot/Makefile
new file mode 100644
index 0000000..514b227
--- /dev/null
+++ b/sys/i386/boot/cdboot/Makefile
@@ -0,0 +1,114 @@
+# $Id$
+#
+
+PROG= boot
+# Order is very important on the SRCS line for this prog
+SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S
+SRCS+= probe_keyboard.c io.c cdrom.c malloc.c
+
+.PATH: ${.CURDIR}/../biosboot
+
+BINDIR= /usr/mdec
+BINMODE= 444
+CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \
+ -mno-486 \
+ -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT} -DTIMEOUT=${TIMEOUT}
+CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK}
+CFLAGS+= -I${.CURDIR}/../../.. -I${.CURDIR}/../biosboot
+CFLAGS+= ${CWARNFLAGS}
+#CFLAGS+= -DDEBUG
+
+# Probe the keyboard and use the serial console if the keyboard isn't found.
+.if defined(BOOT_PROBE_KEYBOARD)
+CFLAGS+= -DPROBE_KEYBOARD
+.endif
+
+# Probe the keyboard lock and use the serial console if the keyboard is locked.
+.if defined(BOOT_PROBE_KEYBOARD_LOCK)
+CFLAGS+= -DPROBE_KEYBOARD_LOCK
+.endif
+
+# Force use of the serial console.
+.if defined(BOOT_FORCE_COMCONSOLE)
+CFLAGS+= -DFORCE_COMCONSOLE
+.endif
+
+# By default, if a serial port is going to be used as console, use COM1
+# (aka /dev/ttyd0).
+BOOT_COMCONSOLE_PORT?=0x3F8
+CFLAGS+= -DCOMCONSOLE=${BOOT_COMCONSOLE_PORT}
+
+BOOT_COMCONSOLE_SPEED?=9600
+CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED}
+
+# Enable code to take the default boot string from a fixed location on the
+# disk. See nextboot(8) and README.386BSD for more info.
+#CFLAGS+= -DNAMEBLOCK
+#CFLAGS+= -DNAMEBLOCK_WRITEBACK
+
+# Bias the conversion from the BIOS drive number to the FreeBSD unit number
+# for hard disks. This may be useful for people booting in a mixed IDE/SCSI
+# environment (set BOOT_HD_BIAS to the number of IDE drives).
+#CFLAGS+= -DBOOT_HD_BIAS=1
+#
+# Details: this only applies if BOOT_HD_BIAS > 0. If the BIOS drive number
+# for the boot drive is >= BOOT_HD_BIAS, then the boot drive is assumed to
+# be SCSI and have unit number (BIOS_drive_number - BOOT_HD_BIAS). E.g.,
+# BOOT_HD_BIAS=1 makes BIOS drive 1 correspond to 1:sd(0,a) instead of
+# 1:wd(1,a). If `sd' is given explicitly, then the drive is assumed to be
+# SCSI and have BIOS drive number (sd_unit_number + BOOT_HD_BIAS). E.g.,
+# BOOT_HD_BIAS=1 makes sd(0,a) correspond to 1:sd(0,a) instead of 0:sd(0,a).
+
+CLEANFILES+= boot.nohdr boot.strip boot1 boot2 sizetest
+LDFLAGS+= -N -T 0 -nostdlib
+#LINKS= ${BINDIR}/sdboot ${BINDIR}/wdboot\
+# ${BINDIR}/sdboot ${BINDIR}/fdboot\
+# ${BINDIR}/bootsd ${BINDIR}/bootwd\
+# ${BINDIR}/bootsd ${BINDIR}/bootfd
+NOSHARED= YES
+NOMAN=
+STRIP=
+
+# tunable timeout parameter, waiting for keypress, calibrated in ms
+BOOTWAIT?= 5000
+# tunable timeout during string input, calibrated in ms
+#TIMEOUT?= 30000
+
+# Location that boot2 is loaded at
+BOOTSEG= 0x1000
+
+# Offset in BOOTSEG for the top of the stack, keep this 16 byte aligned
+BOOTSTACK= 0xFFF0
+
+boot.strip: boot
+ cp -p boot boot.strip
+ strip boot.strip
+ size boot.strip
+
+boot.nohdr: boot.strip
+ dd if=boot.strip of=boot.nohdr ibs=32 skip=1 obs=1024b
+ ls -l boot.nohdr
+
+boot1: boot.nohdr
+ dd if=boot.nohdr of=boot1 bs=512 count=1
+
+boot2: boot.nohdr
+ dd if=boot.nohdr of=boot2 bs=512 skip=1
+ @dd if=boot2 skip=14 of=sizetest 2> /dev/null
+ @if [ -s sizetest ] ; then \
+ echo "boot2 is too big" >&2 ; \
+ rm boot2 ; \
+ exit 2 ; \
+ fi
+
+boot.img: boot.nohdr
+ dd if=boot.nohdr of=boot.img bs=1440k count=1 conv=sync
+
+all: boot.img
+
+install:
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\
+ boot.img ${DESTDIR}${BINDIR}/cdboot
+
+.include <bsd.kern.mk>
+.include <bsd.prog.mk>
diff --git a/sys/i386/boot/cdboot/asm.S b/sys/i386/boot/cdboot/asm.S
new file mode 100644
index 0000000..e689817
--- /dev/null
+++ b/sys/i386/boot/cdboot/asm.S
@@ -0,0 +1,278 @@
+/*
+ * 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.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:13 rpd
+ * $Id: asm.S,v 1.9 1996/03/08 07:27:52 bde Exp $
+ */
+
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+ .file "asm.s"
+
+#include "asm.h"
+
+
+CR0_PE_ON = 0x1
+CR0_PE_OFF = 0xfffffffe
+
+ .text
+
+/*
+ *
+ * real_to_prot()
+ * transfer from real mode to protected mode.
+ */
+
+ENTRY(real_to_prot)
+ /* guarantee that interrupt is disabled when in prot mode */
+ cli
+
+ /* load the gdtr */
+ addr32
+ data32
+ lgdt EXT(Gdtr)
+
+ /* set the PE bit of CR0 */
+ mov %cr0, %eax
+
+ data32
+ or $CR0_PE_ON, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intrasegment jump to flush the processor pipeline and
+ * reload CS register
+ */
+ data32
+ ljmp $0x18, $xprot
+xprot:
+
+ /*
+ * we are in USE32 mode now
+ * set up the protected mode segment registers : DS, SS, ES, FS
+ */
+ movw $0x20, %ax /* data segment */
+ mov %ax, %ds /* gas would waste a prefix byte for movw */
+ mov %ax, %ss
+ mov %ax, %es
+ movw $0x10, %ax /* flat segment */
+ mov %ax, %fs
+
+#ifdef BDE_DEBUGGER
+ /* load idtr so we can debug */
+ lidt EXT(Idtr_prot)
+#endif
+
+ ret
+
+/*
+ *
+ * prot_to_real()
+ * transfer from protected mode to real mode
+ *
+ */
+
+ENTRY(prot_to_real)
+
+ /* Prepare %ax while we're still in a mode that gas understands. */
+ movw $0x30, %ax
+
+ /* Change to use16 mode. */
+ ljmp $0x28, $x16
+x16:
+
+ mov %ax, %ds
+ mov %ax, %ss
+ mov %ax, %es
+ mov %ax, %fs
+
+ /* clear the PE bit of CR0 */
+ mov %cr0, %eax
+ data32
+ and $CR0_PE_OFF, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intersegment jmp to flush the processor pipeline
+ * and reload CS register
+ */
+ data32
+ ljmp $BOOTSEG, $xreal
+xreal:
+
+ /*
+ * we are in real mode now
+ * set up the real mode segment registers : DS, SS, ES, FS
+ */
+ mov %cs, %ax
+ mov %ax, %ds
+ mov %ax, %ss
+ mov %ax, %es
+ mov %ax, %fs
+
+#ifdef BDE_DEBUGGER
+ /* load idtr so we can debug */
+ addr32
+ data32
+ lidt EXT(Idtr_real)
+#endif
+
+ data32
+ ret
+
+/*
+ * startprog(phyaddr)
+ * start the program on protected mode where phyaddr is the entry point
+ *
+ * XXX This whole mess should go away and we should run the boot code in
+ * flat 32 bit mode with it linked -T BOOTSEG. See the netboot code for
+ * how this is done.
+ */
+
+ENTRY(startprog)
+ push %ebp
+ mov %esp, %ebp
+ movl %esp, %eax /* Use eax as the old stack pointer */
+
+ /* convert the current stack to a 32 bit flat model */
+ movw $0x10, %bx
+ mov %bx, %ss
+ addl $(BOOTSEG<<4),%esp
+
+ /* copy the arguments from the old stack to the new stack */
+ pushl 0x14(%eax) /* &bootinfo */
+ pushl $0 /* was &nfsdiskless */
+ pushl $0 /* was esym */
+ pushl $0 /* was cyloffset */
+ pushl 0x10(%eax) /* bootdev */
+ pushl 0x0C(%eax) /* howto */
+ movl $(ourreturn),%ebx
+ addl $(BOOTSEG<<4),%ebx /* Fix it up for flat segments */
+ pushl %ebx /* our return address */
+
+ /* push on our entry address */
+ pushl $0x08 /* segment selector */
+ pushl 0x08(%eax) /* kernel entry address */
+
+ /* convert over the other data segs */
+ movw $0x10, %bx
+ mov %bx, %ds
+ mov %bx, %es
+
+ /* convert the PC (and code seg) */
+ lret
+ourreturn:
+ /* For now there is not much we can do, just lock in a loop */
+ jmp ourreturn
+
+/*
+ *
+ * pbzero( dst, cnt)
+ * where src is a virtual address and dst is a physical address
+ */
+
+ENTRY(pbzero)
+ push %ebp
+ mov %esp, %ebp
+ push %es
+ push %esi
+ push %edi
+ push %ecx
+
+ cld
+
+ /* set %es to point at the flat segment */
+ movw $0x10, %ax
+ mov %ax, %es
+
+ mov 0x8(%ebp), %edi /* destination */
+ mov 0xc(%ebp), %ecx /* count */
+ xorl %eax, %eax /* value 0 */
+
+ rep
+ stosb
+
+ pop %ecx
+ pop %edi
+ pop %esi
+ pop %es
+ pop %ebp
+
+ ret
+/*
+ * pcpy(src, dst, cnt)
+ * where src is a virtual address and dst is a physical address
+ */
+
+ENTRY(pcpy)
+ push %ebp
+ mov %esp, %ebp
+ push %es
+ push %esi
+ push %edi
+ push %ecx
+
+ cld
+
+ /* set %es to point at the flat segment */
+ movw $0x10, %ax
+ mov %ax, %es
+
+ mov 0x8(%ebp), %esi /* source */
+ mov 0xc(%ebp), %edi /* destination */
+ mov 0x10(%ebp), %ecx /* count */
+
+ rep
+ movsb
+
+ pop %ecx
+ pop %edi
+ pop %esi
+ pop %es
+ pop %ebp
+
+ ret
diff --git a/sys/i386/boot/cdboot/bios.S b/sys/i386/boot/cdboot/bios.S
new file mode 100644
index 0000000..99c8c94
--- /dev/null
+++ b/sys/i386/boot/cdboot/bios.S
@@ -0,0 +1,411 @@
+/*
+ * 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.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:26 rpd
+ * $Id$
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Extensions for El Torito CD-ROM booting:
+ *
+ * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO
+ * Copyright © 1997 interface business GmbH, Dresden.
+ * All rights reserved.
+ *
+ * This code has been written by Jörg Wunsch, Dresden.
+ * Direct comments to <joerg_wunsch@interface-business.de>.
+ *
+ * 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(S) ``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(S) 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 "bios.s"
+
+#include "asm.h"
+ .text
+
+/*
+ * int
+ * getbootspec(struct specpacket *offset)
+ *
+ * Read CD-ROM boot specification packet to "offset".
+ */
+ENTRY(getbootspec)
+ push %ebp
+ mov %esp, %ebp
+
+ push %esi
+ push %ebx
+
+ movw 0x8(%ebp), %si
+ mov $0x7f, %edx
+
+ /* prot_to_real will set %es to BOOTSEG */
+ call EXT(prot_to_real) /* enter real mode */
+ movw $0x4b01, %ax /* (do not) terminate disk emulation */
+ movb $0x7f, %dl /* any drive */
+
+ sti
+ int $0x13
+ cli
+
+ /* save return value (actually movw %ax, %bx) */
+ mov %eax, %ebx
+
+ data32
+ call EXT(real_to_prot) /* back to protected mode */
+
+ xor %eax, %eax
+ movb %bh, %al /* return value in %ax */
+
+ pop %ebx
+ pop %esi
+ pop %ebp
+
+ ret
+
+
+/*
+ * int
+ * biosreadlba(struct daddrpacket *daddr)
+ * Read sectors using the BIOS "read extended" function
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ * Call with %ah = 0x42
+ * %dl = drive (0x0 for floppy disk, or emulated CD)
+ * %ds:%si = ptr to disk address packet
+ * Return:
+ * %ah = 0x0 on success; err code on failure
+ */
+
+ENTRY(biosreadlba)
+ push %ebp
+ mov %esp, %ebp
+
+ push %ebx
+ push %esi
+
+ movw 8(%ebp), %si
+ movl $0, %edx /* emulated CD is always drive 0 */
+
+ /* prot_to_real will set %es to BOOTSEG */
+ call EXT(prot_to_real) /* enter real mode */
+ movw $0x4200, %ax /* subfunction */
+ movb $0, %dl
+
+ sti
+ int $0x13
+ cli
+
+ /* save return value (actually movw %ax, %bx) */
+ mov %eax, %ebx
+
+ data32
+ call EXT(real_to_prot) /* back to protected mode */
+
+ xor %eax, %eax
+ movb %bh, %al /* return value in %ax */
+
+ pop %esi
+ pop %ebx
+ pop %ebp
+
+ ret
+
+/*
+ * putc(ch)
+ * BIOS call "INT 10H Function 0Eh" to write character to console
+ * Call with %ah = 0x0e
+ * %al = character
+ * %bh = page
+ * %bl = foreground color ( graphics modes)
+ */
+
+
+ENTRY(putc)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ movb 0x8(%ebp), %cl
+
+ call EXT(prot_to_real)
+
+ data32
+ mov $0x1, %ebx /* %bh=0, %bl=1 (blue) */
+ movb $0xe, %ah
+ movb %cl, %al
+ sti
+ int $0x10 /* display a byte */
+ cli
+
+ data32
+ call EXT(real_to_prot)
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
+
+/*
+ * getc()
+ * BIOS call "INT 16H Function 00H" to read character from keyboard
+ * Call with %ah = 0x0
+ * Return: %ah = keyboard scan code
+ * %al = ASCII character
+ */
+
+ENTRY(getc)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx /* save %ebx */
+ push %esi
+ push %edi
+
+ call EXT(prot_to_real)
+
+ movb $0x0, %ah
+ sti
+ int $0x16
+ cli
+
+ movb %al, %bl /* real_to_prot uses %eax */
+
+ data32
+ call EXT(real_to_prot)
+
+ xor %eax, %eax
+ movb %bl, %al
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+/*
+ * ischar()
+ * if there is a character pending, return it; otherwise return 0
+ * BIOS call "INT 16H Function 01H" to check whether a character is pending
+ * Call with %ah = 0x1
+ * Return:
+ * If key waiting to be input:
+ * %ah = keyboard scan code
+ * %al = ASCII character
+ * Zero flag = clear
+ * else
+ * Zero flag = set
+ */
+ENTRY(ischar)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ call EXT(prot_to_real) /* enter real mode */
+
+ xor %ebx, %ebx
+ movb $0x1, %ah
+ sti
+ int $0x16
+ cli
+ data32
+ jz nochar
+ movb %al, %bl
+
+nochar:
+ data32
+ call EXT(real_to_prot)
+
+ xor %eax, %eax
+ movb %bl, %al
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
+/*
+ *
+ * get_diskinfo(): return a word that represents the
+ * max number of sectors and heads and drives for this device
+ *
+ */
+
+ENTRY(get_diskinfo)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ movb 0x8(%ebp), %dl /* diskinfo(drive #) */
+ call EXT(prot_to_real) /* enter real mode */
+
+ movb $0x8, %ah /* ask for disk info */
+
+ sti
+ int $0x13
+ cli
+
+ jnc ok
+ /*
+ * Urk. Call failed. It is not supported for floppies by old BIOS's.
+ * Guess it's a 15-sector floppy.
+ */
+ subb %ah, %ah /* %ax = 0 */
+ movb %al, %al
+ movb %ah, %bh /* %bh = 0 */
+ movb $2, %bl /* %bl bits 0-3 = drive type,
+ bit 2 = 1.2M */
+ movb $79, %ch /* max track */
+ movb $15, %cl /* max sector */
+ movb $1, %dh /* max head */
+ movb $1, %dl /* # floppy drives installed */
+ /* es:di = parameter table */
+ /* carry = 0 */
+ok:
+
+ data32
+ call EXT(real_to_prot) /* back to protected mode */
+
+ /*
+ * form a longword representing all this gunk:
+ * 6 bit zero
+ * 10 bit max cylinder (0 based)
+ * 8 bit max head (0 based)
+ * 8 bit zero
+ * 6 bit max sector (1 based) = # sectors
+ */
+ movb %cl, %al /* Upper two bits of cylinder count */
+ andl $192,%eax
+ leal 0(,%eax,4),%eax /* << 2 */
+ movb %ch, %al /* Lower 8 bits */
+ sall $16,%eax /* << 16 */
+ movb %dh, %ah /* max head */
+ andb $0x3f, %cl /* mask of cylinder gunk */
+ movb %cl, %al /* max sector (and # sectors) */
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
+
+/*
+ *
+ * memsize(i) : return the memory size in KB. i == 0 for conventional memory,
+ * i == 1 for extended memory
+ * BIOS call "INT 12H" to get conventional memory size
+ * BIOS call "INT 15H, AH=88H" to get extended memory size
+ * Both have the return value in AX.
+ *
+ */
+
+ENTRY(memsize)
+ push %ebp
+ mov %esp, %ebp
+ push %ebx
+ push %esi
+ push %edi
+
+ mov 8(%ebp), %ebx
+
+ call EXT(prot_to_real) /* enter real mode */
+
+ cmpb $0x1, %bl
+ data32
+ je xext
+
+ sti
+ int $0x12
+ cli
+ data32
+ jmp xdone
+
+xext: movb $0x88, %ah
+ sti
+ int $0x15
+ cli
+
+xdone:
+ pushl $0 /* actually pushw $0 */
+ pushl %eax /* actually pushw %ax */
+
+ data32
+ call EXT(real_to_prot)
+
+ pop %eax
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebp
+ ret
diff --git a/sys/i386/boot/cdboot/boot.c b/sys/i386/boot/cdboot/boot.c
new file mode 100644
index 0000000..0354cc1
--- /dev/null
+++ b/sys/i386/boot/cdboot/boot.c
@@ -0,0 +1,393 @@
+/*
+ * 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.
+ *
+ * from: Mach, [92/04/03 16:51:14 rvb]
+ * $Id$
+ */
+
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Extensions for El Torito CD-ROM booting:
+ *
+ * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO
+ * Copyright © 1997 interface business GmbH, Dresden.
+ * All rights reserved.
+ *
+ * This code was written by Jörg Wunsch, Dresden.
+ * Direct comments to <joerg_wunsch@interface-business.de>.
+ *
+ * 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(S) ``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(S) 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 "boot.h"
+#include <a.out.h>
+#include <sys/reboot.h>
+#include <machine/bootinfo.h>
+#ifdef PROBE_KEYBOARD_LOCK
+#include <machine/cpufunc.h>
+#endif
+
+#define ouraddr (BOOTSEG << 4) /* XXX */
+
+int loadflags;
+
+/*
+ * XXX
+ * By now, only "cd". How do we learn from the BIOS we've been booted off
+ * an ATAPI CD-ROM? Do the non-{cd,wcd} drivers implement El Torito booting
+ * at all?
+ */
+static int maj = 6;
+static struct specpacket spkt = { 0x13 };
+static char *name;
+static char namebuf[128];
+static struct bootinfo bootinfo;
+
+static void getbootdev(char *ptr, int *howto);
+static void loadprog(void);
+
+/* NORETURN */
+void
+boot(int drive)
+{
+ int ret, i;
+
+#ifdef PROBE_KEYBOARD
+ if (probe_keyboard()) {
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf("\nNo keyboard found.");
+ }
+#endif
+
+#ifdef PROBE_KEYBOARD_LOCK
+ if (!(inb(0x64) & 0x10)) {
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf("\nKeyboard locked.");
+ }
+#endif
+
+#ifdef FORCE_COMCONSOLE
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf("\nSerial console forced.");
+#endif
+
+ /* Pick up the story from the Bios on geometry of disks */
+
+ /*
+ * XXX
+ * Do we need to defer this until we can relinguish the
+ * BIOS emulation?
+ */
+
+ for(ret = 0; ret < N_BIOS_GEOM; ret ++)
+ bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
+
+ bootinfo.bi_basemem = memsize(0);
+ bootinfo.bi_extmem = memsize(1);
+ bootinfo.bi_memsizes_valid = 1;
+
+ gateA20();
+
+ ret = getbootspec(&spkt);
+ if (ret != 0) {
+ printf("Your BIOS int 0x13 extensions seem to be disabled.\n"
+ "It's impossible to boot a CD-ROM without them.\n"
+ "(BIOS int 0x13 fn 0x4b01 yielded error %d)\n",
+ ret);
+ while (1)
+ ;
+ }
+
+ if (devopen(sessionstart) == -1)
+ printf("Warning: cannot open default session.\n"
+ "Maybe your BIOS int 0x13 extensions are disabled?\n"
+ "You need them in order to boot a CD-ROM.\n");
+
+ for (;;) {
+
+ /*
+ * The El Torito specification stinks. Not only this
+ * crappy idea of `emulation booting' (and at least
+ * earlier versions of the AHA-2940 BIOS didn't
+ * implement anything else than floppy emulation
+ * booting), but note also that there's absolutely no
+ * way via the BIOS to obtain the starting LBA of your
+ * session. All you can get ahold of is the LBA of
+ * that funny emulated disk. Since this one just
+ * happens to be a file hidden inside the ISO9660
+ * filesystem, it is located at a varying offset from
+ * the start of the session. We therefore allow to
+ * specify the starting block of the session to use in
+ * the boot string, so the operator can specify the
+ * session to boot from. However, (s)he needs to know
+ * the RBA for the session from the CD-ROM TOC.
+ */
+ DPRINTF(("using session at sector %d\n", sessionstart));
+
+ name = "/kernel";
+ printf("\n>> FreeBSD CD-ROM BOOT\n"
+ "Usage: [@%d]%s[-abcCdghrsv]\n"
+ "Use ? for file list or press Enter for defaults\n"
+ "\nBoot: ",
+ sessionstart, name);
+
+ loadflags &= RB_SERIAL; /* clear all, but leave serial console */
+ loadflags |= RB_CDROM; /* ...and default to CD-ROM root. */
+
+ getbootdev(namebuf, &loadflags);
+
+ DPRINTF(("Selected: name=`%s', loadflags=0x%x\n",
+ name, loadflags));
+
+ ret = openrd(name);
+
+ DPRINTF(("openrd() = %d\n", ret));
+
+ if (ret != 0) {
+ if (ret > 0)
+ printf("Can't find %s\n", name);
+ continue;
+ }
+ loadprog();
+ }
+}
+
+static void
+loadprog(void)
+{
+ struct exec head;
+ u_int32_t startaddr, addr, bootdev;
+ int i;
+ unsigned pad;
+
+ seek(0);
+ if (read((void *)&head, sizeof(head)) == -1 ||
+ N_BADMAG(head)) {
+ printf("Invalid format!\n");
+ return;
+ }
+
+ /*
+ * We assume that the entry address is the same as the lowest text
+ * address and that the kernel startup code handles relocation by
+ * this address rounded down to a multiple of 16M.
+ */
+ startaddr = head.a_entry & 0x00FFFFFF;
+ addr = startaddr;
+ printf("Booting CD-ROM [@%d]%s @ 0x%x\n", sessionstart, name, addr);
+ if(addr < 0x00100000)
+ {
+ /*
+ * Bail out, instead of risking to damage the BIOS
+ * variables, the loader, or the adapter memory area.
+ * We don't support loading below 1 MB any more.
+ */
+ printf("Start address too low\n");
+ return;
+ }
+ printf("text=0x%x ", head.a_text);
+
+ /* load the text segment */
+ seek(N_TXTOFF(head));
+ if (xread((void *)addr, head.a_text) == -1)
+ return;
+ addr += head.a_text;
+
+ /* Pad to a page boundary. */
+ pad = (unsigned)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ pbzero((void *)addr, pad);
+ addr += pad;
+ }
+
+ /* load the initialised data after the text */
+ printf("data=0x%x ", head.a_data);
+ if (xread((void *)addr, head.a_data) == -1)
+ return;
+ addr += head.a_data;
+
+ /* Skip over the uninitialised data (but clear it) */
+ printf("bss=0x%x ", head.a_bss);
+
+/*
+ * XXX however, we should be checking that we don't load ... into
+ * nonexistent memory. A full symbol table is unlikely to fit on 4MB
+ * machines.
+ */
+ pbzero((void *)addr, head.a_bss);
+ addr += head.a_bss;
+
+ /* Pad to a page boundary. */
+ pad = (unsigned)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ addr += pad;
+ }
+ bootinfo.bi_symtab = addr;
+
+ /* Copy the symbol table size */
+ pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
+ addr += sizeof(head.a_syms);
+
+ /* Load the symbol table */
+ printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
+ head.a_syms);
+ if (xread((void *)addr, head.a_syms) == -1)
+ return;
+ addr += head.a_syms;
+
+ /* Load the string table size */
+ if (read((void *)&i, sizeof(int)) == -1)
+ return;
+ pcpy(&i, (void *)addr, sizeof(int));
+ i -= sizeof(int);
+ addr += sizeof(int);
+
+ /* Load the string table */
+ printf("+0x%x+0x%x]\n", sizeof(int), i);
+ if (xread((void *)addr, i) == -1)
+ return;
+ addr += i;
+
+ bootinfo.bi_esymtab = addr;
+
+ /* XXX what else can we say about a CD-ROM? */
+ bootdev = MAKEBOOTDEV(maj, 0, 0, 0, 0);
+
+ bootinfo.bi_version = BOOTINFO_VERSION;
+ bootinfo.bi_kernelname = name + ouraddr;
+ bootinfo.bi_nfs_diskless = NULL;
+ bootinfo.bi_size = sizeof(bootinfo);
+ printf("total=0x%x entry point=0x%x\n", (int)addr, (int)startaddr);
+ startprog((int)startaddr, loadflags | RB_BOOTINFO, bootdev,
+ (int)&bootinfo + ouraddr);
+}
+
+static void
+getbootdev(char *ptr, int *howto)
+{
+ char c;
+
+ /*
+ * Be paranoid and make doubly sure that the input buffer is empty.
+ */
+ if (*howto & RB_SERIAL)
+ init_serial();
+
+ if (!gets(ptr)) {
+ putchar('\n');
+ return;
+ }
+ while ((c = *ptr) != '\0') {
+nextarg:
+ while (c == ' ')
+ c = *++ptr;
+ if (c == '-')
+ while ((c = *++ptr) != '\0') {
+ if (c == ' ')
+ goto nextarg;
+ if (c == 'C')
+ *howto &= ~RB_CDROM;
+ if (c == 'a')
+ *howto |= RB_ASKNAME;
+ if (c == 'b')
+ *howto |= RB_HALT;
+ if (c == 'c')
+ *howto |= RB_CONFIG;
+ if (c == 'd')
+ *howto |= RB_KDB;
+ if (c == 'h') {
+ *howto ^= RB_SERIAL;
+ if (*howto & RB_SERIAL)
+ init_serial();
+ continue;
+ }
+ if (c == 'g')
+ *howto |= RB_GDB;
+ if (c == 'r')
+ *howto |= RB_DFLTROOT;
+ if (c == 's')
+ *howto |= RB_SINGLE;
+ if (c == 'v')
+ *howto |= RB_VERBOSE;
+ }
+ if (c == '\0')
+ return;
+ name = ptr;
+ while (*++ptr != '\0') {
+ if (*ptr == ' ') {
+ *ptr++ = '\0';
+ break;
+ }
+ }
+ }
+}
diff --git a/sys/i386/boot/cdboot/boot.h b/sys/i386/boot/cdboot/boot.h
new file mode 100644
index 0000000..b71f457
--- /dev/null
+++ b/sys/i386/boot/cdboot/boot.h
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:35:03 rpd
+ * $Id$
+ */
+/*
+ * Extensions for El Torito CD-ROM booting:
+ *
+ * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO
+ * Copyright © 1997 interface business GmbH, Dresden.
+ * All rights reserved.
+ *
+ * This code has been written by Jörg Wunsch, Dresden.
+ * Direct comments to <joerg_wunsch@interface-business.de>.
+ *
+ * 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(S) ``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(S) 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/time.h>
+
+/*
+ * Specification packet per El Torito, BIOS int 0x13 fn 0x4b00/0x4b01
+ */
+struct specpacket
+{
+ u_char size; /* must be 0x13 */
+ u_char mediatype; /*
+ * 0 - no emulation
+ * 1 - 1.2 MB floppy
+ * 2 - 1.44 MB floppy
+ * 3 - 2.88 MB floppy
+ * 4 - hard disk C:
+ */
+ u_char drvno; /* emulated drive number */
+ u_char ctrlindx; /* controller index, see El Torito */
+ u_int32_t lba; /* LBA of emulated disk drive */
+ u_int16_t devspec; /* device specification, see El Torito */
+ u_int16_t ubufseg; /* user buffer segment */
+ u_int16_t loadseg; /* load segment; 0 => use BIOS default 0x7c0 */
+ u_int16_t seccnt; /* number of auto-loaded (virtual) sectors */
+ u_char cyls; /* same values as in int 0x13, fn 8 */
+ u_char secs;
+ u_char heads;
+};
+
+/*
+ * Disk address packet for extended BIOS int 0x13 fn's 0x41...0x48.
+ */
+struct daddrpacket
+{
+ u_char size; /* size of daddrpacket, must be 0x10 */
+ u_char reserved1;
+ u_char nblocks; /*
+ * number of 512-byte blocks to transfer,
+ * must be <= 127
+ */
+ u_char reserved2;
+ u_int16_t boffs; /* bseg:boffs denominate the transfer buffer */
+ u_int16_t bseg;
+ u_int32_t lba; /* actually a 64-bit type, but 64-bit arith */
+ u_int32_t lbahigh; /* is expensive, and we don't really need it */
+};
+
+#ifdef DEBUG
+# define DPRINTF(x) printf x
+#else
+# define DPRINTF(x)
+#endif
+
+
+/* asm.S */
+#if ASM_ONLY
+void real_to_prot(void);
+void prot_to_real(void);
+#endif
+void startprog(unsigned int physaddr, int howto, int bootdev,
+ /* XXX struct bootinfo * */ unsigned int bootinfo);
+void pbzero(void *dst, size_t count);
+void pcpy(const void *src, void *dst, size_t count);
+
+/* bios.S */
+
+int biosread(int dev, int cyl, int head, int sec, int nsec, void *offset);
+int getbootspec(struct specpacket *offset);
+int biosreadlba(struct daddrpacket *daddr);
+void putc(int c);
+int getc(void);
+int ischar(void);
+int get_diskinfo(int drive);
+int memsize(int extended);
+
+/* boot.c */
+extern int loadflags;
+
+void boot(int drive);
+
+/* boot2.S */
+void boot2(void);
+
+/* cdrom.c */
+extern u_int32_t sessionstart;
+
+int devopen(u_int32_t session);
+void seek(u_int32_t offs);
+int read(u_char *addr, size_t size);
+int xread(u_char *addr, size_t size);
+int openrd(char *name);
+
+/* io.c */
+void gateA20(void);
+void printf(const char *format, ...);
+void putchar(int c);
+void delay1ms(void);
+int gets(char *buf);
+int strncasecmp(const char *s1, const char *s2, size_t s);
+void bcopy(const void *from, void *to, size_t len);
+void twiddle(void);
+
+/* probe_keyboard.c */
+int probe_keyboard(void);
+
+/* serial.S */
+void serial_putc(int ch);
+int serial_getc(void);
+int serial_ischar(void);
+void init_serial(void);
+
+/* table.c */
+extern char *devs[];
+extern unsigned long tw_chars;
+
+/* malloc.c */
+void *malloc(size_t size);
+void free(void *chunk);
+
+/* linker stuff */
+extern void end;
diff --git a/sys/i386/boot/cdboot/cdrom.c b/sys/i386/boot/cdboot/cdrom.c
new file mode 100644
index 0000000..03081d9
--- /dev/null
+++ b/sys/i386/boot/cdboot/cdrom.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO
+ * Copyright © 1997 interface business GmbH, Dresden.
+ * All rights reserved.
+ *
+ * This code was written by Jörg Wunsch, Dresden.
+ * Direct comments to <joerg_wunsch@interface-business.de>.
+ *
+ * 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(S) ``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(S) 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.
+ *
+ * $Id$
+ */
+
+
+#include "boot.h"
+
+#include <isofs/cd9660/iso.h>
+
+#define BLKSIZE 2048 /* CD-ROM data block size */
+#define BIOSSEC 512 /* BIOS sector size */
+
+#define CD2LBA(rba) ((rba) << 2) /* CD-ROM relative block to BIOS LBA */
+
+u_int32_t sessionstart;
+
+static struct iso_primary_descriptor pdesc;
+
+static char *rootdirbuf;
+static size_t rootdirsize;
+static char xbuf[BLKSIZE];
+static u_int32_t curblk, startblk, filesize, offset;
+
+static int bread(u_int32_t rba, size_t nblks, void *buf);
+static void badread(const char *msg, u_int32_t blkno);
+static struct iso_directory_record *find(const char *path, int list_only);
+static int iread(u_char *buf, size_t len,
+ void (*copyfun)(const void *src, void *dst, size_t size));
+
+static struct daddrpacket dpkt = { 0x10 };
+
+int
+devopen(u_int32_t session)
+{
+ int rv;
+ u_int32_t rootdirblk;
+ struct iso_directory_record *rootdirp;
+
+ if ((rv = bread(session + 16, 1, &pdesc)) != 0) {
+ printf("Error reading primary ISO descriptor: %d\n", rv);
+ return -1;
+ }
+ rootdirp = (struct iso_directory_record *)pdesc.root_directory_record;
+ rootdirblk = isonum_733(rootdirp->extent);
+ rootdirsize = isonum_733(rootdirp->size);
+
+ /* just in case, round up */
+ rootdirsize = (rootdirsize + BLKSIZE - 1) & ~(BLKSIZE - 1);
+
+ if (rootdirbuf != NULL)
+ free(rootdirbuf);
+ if ((rootdirbuf = malloc(rootdirsize)) == 0) {
+ printf("Cannot allocate memory for the root "
+ "directory buffer.\n");
+ return -1;
+ }
+ if ((rv = bread(rootdirblk, rootdirsize / BLKSIZE, rootdirbuf))
+ != 0) {
+ printf("Error reading root directory: %d\n", rv);
+ return -1;
+ }
+
+ DPRINTF(("Root directory is 0x%x bytes @ %d\n",
+ rootdirsize, rootdirblk));
+
+ return 0;
+}
+
+static int
+bread(u_int32_t rba, size_t nblks, void *buf)
+{
+ int i, rv;
+
+ for (i = 0, rv = -1; rv != 0 && i < 3; i++) {
+ dpkt.nblocks = nblks * (BLKSIZE / BIOSSEC);
+ dpkt.boffs = (u_int16_t)((int)buf & 0xffff);
+ dpkt.bseg = BOOTSEG;
+ dpkt.lba = CD2LBA(rba);
+
+#ifdef DEBUG_VERBOSE
+ DPRINTF(("Calling biosreadlba(%d blocks, lba %d) = ",
+ dpkt.nblocks, dpkt.lba));
+#endif
+
+ rv = biosreadlba(&dpkt);
+
+#ifdef DEBUG_VERBOSE
+ DPRINTF(("%d\n", rv));
+#endif
+ }
+ return rv;
+}
+
+
+void
+seek(u_int32_t offs)
+{
+ offset = offs;
+}
+
+static void
+badread(const char *msg, u_int32_t blkno)
+{
+ printf("Error reading block %d from CD-ROM: %s\n",
+ blkno, msg);
+}
+
+static __inline size_t
+minlen(size_t a, size_t b)
+{
+ return a < b? a: b;
+}
+
+/*
+ * Internal form of read()/xread().
+ */
+static int
+iread(u_char *buf, size_t len,
+ void (*copyfun)(const void *src, void *dst, size_t size))
+{
+ u_int32_t newblk, ptr;
+ size_t bsize;
+
+ newblk = offset / BLKSIZE + startblk;
+
+ if (newblk != curblk) {
+ if (offset + len >= filesize) {
+ badread("access beyond file limit", newblk);
+ return -1;
+ }
+ if (bread(newblk, 1, xbuf)) {
+ badread("BIOS read error", newblk);
+ return -1;
+ }
+ curblk = newblk;
+ }
+ ptr = offset & (BLKSIZE - 1);
+ if (ptr > 0) {
+ /* initial short transfer */
+ bsize = minlen(BLKSIZE - ptr, len);
+ copyfun(xbuf + ptr, buf, bsize);
+ buf += bsize;
+ len -= bsize;
+ offset += bsize;
+ }
+ for (; len > 0; len -= bsize) {
+ bsize = minlen(len, BLKSIZE);
+ newblk = offset / BLKSIZE + startblk;
+
+ if (newblk != curblk) {
+ if (offset + bsize > filesize) {
+ badread("access beyond file limit", newblk);
+ return -1;
+ }
+ if (bread(newblk, 1, xbuf)) {
+ badread("BIOS read error", newblk);
+ return -1;
+ }
+ curblk = newblk;
+ }
+ copyfun(xbuf, buf, bsize);
+ buf += bsize;
+ offset += bsize;
+ }
+ return 0;
+}
+
+int
+read(u_char *buf, size_t len)
+{
+ DPRINTF(("read(0x%x, %d)\n", (int)buf, len));
+ return iread(buf, len, bcopy);
+}
+
+int
+xread(u_char *buf, size_t len)
+{
+ DPRINTF(("xread(0x%x, %d)\n", (int)buf, len));
+ return iread(buf, len, pcpy);
+}
+
+/*
+ * XXX Todo:
+ * Use RR attributes if present
+ */
+static struct iso_directory_record *
+find(const char *path, int list_only)
+{
+ struct iso_directory_record *dirp;
+ char *ptr;
+ size_t len, entrylen;
+ char namebuf[256];
+ int i;
+
+ while (*path && *path == '/')
+ path++;
+
+ for (ptr = rootdirbuf, i = 1;
+ ptr < rootdirbuf + rootdirsize;
+ ptr += entrylen, i++) {
+ dirp = (struct iso_directory_record *)ptr;
+ entrylen = (u_char)dirp->length[0];
+ len = (u_char)dirp->name_len[0];
+
+ DPRINTF(("# %d: offset 0x%x, length 0x%x = %d, ",
+ i, (int)(ptr - rootdirbuf), entrylen, entrylen));
+
+ if (entrylen == 0) {
+ DPRINTF(("EOD\n"));
+ break;
+ }
+ if (len == 0) {
+ DPRINTF(("name_len 0\n"));
+ continue;
+ }
+ if (len == 1 &&
+ (dirp->name[0] == '\0' || dirp->name[1] == '\1')) {
+ DPRINTF(("dot/dot-dot entry\n"));
+ continue;
+ }
+ /* don't consider directories */
+ if (dirp->flags[0] & 2) {
+ DPRINTF(("directory\n"));
+ continue;
+ }
+
+#ifdef DEBUG
+ bcopy(dirp->name, namebuf, len);
+ namebuf[len] = 0;
+ DPRINTF(("name `%s'\n", namebuf));
+#else /* !DEBUG */
+ if (list_only) {
+ bcopy(dirp->name, namebuf, len);
+ namebuf[len] = 0;
+ printf("%s ", namebuf);
+ }
+#endif /* DEBUG */
+
+ if (!list_only &&
+ strncasecmp(path, dirp->name, len) == 0)
+ return dirp;
+ }
+#ifndef DEBUG
+ if (list_only)
+ printf("\n");
+#endif
+ return 0;
+}
+
+int
+openrd(char *name)
+{
+ char *cp;
+ const char *fname;
+ u_int32_t oldsession;
+ int session, list_only;
+ struct iso_directory_record *dirp;
+
+ session = 0;
+ fname = name;
+
+ /*
+ * We accept the following boot string:
+ *
+ * [@sessionstart] name
+ */
+ for (cp = name; *cp; cp++)
+ switch (*cp) {
+ /* we don't support filenames with spaces */
+ case ' ': case '\t':
+ break;
+
+ case '@':
+ if (session) {
+ printf("Syntax error\n");
+ return -1;
+ }
+ session++;
+ oldsession = sessionstart;
+ sessionstart = 0;
+ break;
+
+ case '0': case '1': case '2':
+ case '3': case '4': case '5':
+ case '6': case '7': case '8':
+ case '9':
+ if (session == 1) {
+ sessionstart *= 10;
+ sessionstart += *cp - '0';
+ }
+ break;
+
+ default:
+ if (session == 1) {
+ session++;
+ fname = cp;
+ }
+ }
+
+ if (session && devopen(sessionstart) == -1) {
+ (void)devopen(oldsession);
+ sessionstart = oldsession;
+ }
+ if (session == 1)
+ /* XXX no filename, only session arg */
+ return -1;
+
+ list_only = fname[0] == '?' && fname[1] == 0;
+
+ DPRINTF(("Calling find(%s, %d):\n", fname, list_only));
+ dirp = find(fname, list_only);
+ DPRINTF(("find() returned 0x%x\n", (int)dirp));
+
+ if (list_only)
+ return -1;
+ if (dirp == 0)
+ return 1;
+
+ startblk = isonum_733(dirp->extent);
+ filesize = isonum_733(dirp->size);
+
+ DPRINTF(("startblk = %d, filesize = %d\n", startblk, filesize));
+
+ curblk = 0; /* force a re-read, 0 is impossible file start */
+ seek(0);
+
+ return 0;
+}
diff --git a/sys/i386/boot/cdboot/io.c b/sys/i386/boot/cdboot/io.c
new file mode 100644
index 0000000..dc03262
--- /dev/null
+++ b/sys/i386/boot/cdboot/io.c
@@ -0,0 +1,287 @@
+/*
+ * 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.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:35:57 rpd
+ * $Id$
+ */
+
+#include "boot.h"
+#include <machine/cpufunc.h>
+#include <sys/reboot.h>
+
+#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
+#define K_STATUS 0x64 /* keyboard status */
+#define K_CMD 0x64 /* keybd ctlr command (write-only) */
+
+#define K_OBUF_FUL 0x01 /* output buffer full */
+#define K_IBUF_FUL 0x02 /* input buffer full */
+
+#define KC_CMD_WIN 0xd0 /* read output port */
+#define KC_CMD_WOUT 0xd1 /* write output port */
+#define KB_A20 0xdf /* enable A20,
+ enable output buffer full interrupt
+ enable data line
+ enable clock line */
+
+
+static int getchar(int in_buf);
+
+/*
+ * Gate A20 for high memory
+ */
+void
+gateA20(void)
+{
+#ifdef IBM_L40
+ outb(0x92, 0x2);
+#else /* IBM_L40 */
+ while (inb(K_STATUS) & K_IBUF_FUL);
+ while (inb(K_STATUS) & K_OBUF_FUL)
+ (void)inb(K_RDWR);
+
+ outb(K_CMD, KC_CMD_WOUT);
+ while (inb(K_STATUS) & K_IBUF_FUL);
+ outb(K_RDWR, KB_A20);
+ while (inb(K_STATUS) & K_IBUF_FUL);
+#endif /* IBM_L40 */
+}
+
+/* printf - only handles %d as decimal, %c as char, %s as string */
+
+void
+printf(const char *format, ...)
+{
+ int *dataptr = (int *)&format;
+ char c;
+
+ dataptr++;
+ while ((c = *format++))
+ if (c != '%')
+ putchar(c);
+ else
+ switch (c = *format++) {
+ case 'd': {
+ int num = *dataptr++;
+ char buf[10], *ptr = buf;
+ if (num<0) {
+ num = -num;
+ putchar('-');
+ }
+ do
+ *ptr++ = '0'+num%10;
+ while (num /= 10);
+ do
+ putchar(*--ptr);
+ while (ptr != buf);
+ break;
+ }
+ case 'x': {
+ unsigned int num = *dataptr++, dig;
+ char buf[8], *ptr = buf;
+ do
+ *ptr++ = (dig=(num&0xf)) > 9?
+ 'a' + dig - 10 :
+ '0' + dig;
+ while (num >>= 4);
+ do
+ putchar(*--ptr);
+ while (ptr != buf);
+ break;
+ }
+ case 'c': putchar((*dataptr++)&0xff); break;
+ case 's': {
+ char *ptr = (char *)*dataptr++;
+ while ((c = *ptr++))
+ putchar(c);
+ break;
+ }
+ }
+}
+
+void
+putchar(int c)
+{
+ if (c == '\n') {
+ if (loadflags & RB_SERIAL)
+ serial_putc('\r');
+ else
+ putc('\r');
+ }
+ if (loadflags & RB_SERIAL)
+ serial_putc(c);
+ else
+ putc(c);
+}
+
+static int
+getchar(int in_buf)
+{
+ int c;
+
+loop:
+ if ((c = ((loadflags & RB_SERIAL) ? serial_getc() : getc())) == '\r')
+ c = '\n';
+ if (c == '\b') {
+ if (in_buf != 0) {
+ putchar('\b');
+ putchar(' ');
+ } else {
+ goto loop;
+ }
+ }
+ putchar(c);
+ return(c);
+}
+
+#ifdef PROBE_KEYBOARD
+/*
+ * This routine uses an inb to an unused port, the time to execute that
+ * inb is approximately 1.25uS. This value is pretty constant across
+ * all CPU's and all buses, with the exception of some PCI implentations
+ * that do not forward this I/O adress to the ISA bus as they know it
+ * is not a valid ISA bus address, those machines execute this inb in
+ * 60 nS :-(.
+ *
+ * XXX this should be converted to use bios_tick.
+ */
+void
+delay1ms(void)
+{
+ int i = 800;
+ while (--i >= 0)
+ (void)inb(0x84);
+}
+#endif /* PROBE_KEYBOARD */
+
+static __inline int
+isch(void)
+{
+ int isc;
+
+ /*
+ * Checking the keyboard has the side effect of enabling clock
+ * interrupts so that bios_tick works. Check the keyboard to
+ * get this side effect even if we only want the serial status.
+ */
+ isc = ischar();
+
+ if (!(loadflags & RB_SERIAL))
+ return (isc);
+ return (serial_ischar());
+
+}
+
+static __inline unsigned
+pword(unsigned physaddr)
+{
+ unsigned result;
+
+ /*
+ * Give the fs prefix separately because gas omits it for
+ * "movl %fs:0x46c, %eax".
+ */
+ __asm __volatile("fs; movl %1, %0" : "=r" (result)
+ : "m" (*(unsigned *)physaddr));
+ return (result);
+}
+
+int
+gets(char *buf)
+{
+#define bios_tick pword(0x46c)
+#define BIOS_TICK_MS 55
+ unsigned initial_bios_tick;
+ char *ptr=buf;
+
+#if BOOTWAIT
+ for (initial_bios_tick = bios_tick;
+ bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;)
+#endif
+ if (isch())
+ for (;;) {
+ switch(*ptr = getchar(ptr - buf) & 0xff) {
+ case '\n':
+ case '\r':
+ *ptr = '\0';
+ return 1;
+ case '\b':
+ if (ptr > buf) ptr--;
+ continue;
+ default:
+ ptr++;
+ }
+#if TIMEOUT + 0
+#if !BOOTWAIT
+#error "TIMEOUT without BOOTWAIT"
+#endif
+ for (initial_bios_tick = bios_tick;;) {
+ if (isch())
+ break;
+ if (bios_tick - initial_bios_tick >=
+ TIMEOUT / BIOS_TICK_MS)
+ return 0;
+ }
+#endif
+ }
+ return 0;
+}
+
+int
+strncasecmp(const char *s1, const char *s2, size_t s)
+{
+ /*
+ * We only consider ASCII chars and don't anticipate
+ * control characters (they are invalid in filenames
+ * anyway).
+ */
+ while (s > 0 && (*s1 & 0x5f) == (*s2 & 0x5f)) {
+ if (!*s1++)
+ return 0;
+ s2++;
+ }
+ if (s == 0)
+ return 0;
+ return 1;
+}
+
+void
+bcopy(const void *from, void *to, size_t len)
+{
+ char *fp = (char *)from;
+ char *tp = (char *)to;
+
+ while (len-- > 0)
+ *tp++ = *fp++;
+}
+
+/* To quote Ken: "You are not expected to understand this." :) */
+
+void
+twiddle(void)
+{
+ putchar((char)tw_chars);
+ tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);
+ putchar('\b');
+}
diff --git a/sys/i386/boot/cdboot/malloc.c b/sys/i386/boot/cdboot/malloc.c
new file mode 100644
index 0000000..2b8486d
--- /dev/null
+++ b/sys/i386/boot/cdboot/malloc.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO
+ * Copyright © 1997 interface business GmbH, Dresden.
+ * All rights reserved.
+ *
+ * This code was written by Jörg Wunsch, Dresden.
+ * Direct comments to <joerg_wunsch@interface-business.de>.
+ *
+ * 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(S) ``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(S) 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Simple memory allocator for the bootstrap loader. Probably suffers
+ * a lot from fragmentation.
+ */
+
+#include "boot.h"
+
+#include <stddef.h>
+
+/* ``Nobody will ever need more than 640 KB of RAM.'' :-) */
+#define MAXBRK (640 * 1024 * 1024)
+
+/* allocation unit */
+#define NCHUNKS 2048
+
+struct chunk
+{
+ struct chunk *next;
+ size_t len;
+};
+
+static void *brkval;
+static struct chunk *freelist;
+
+void *
+malloc(size_t len)
+{
+ struct chunk *p, *q, *oldp;
+ size_t nelems;
+
+ nelems = (len + sizeof(struct chunk) - 1) / sizeof(struct chunk) + 1;
+
+ /*
+ * First, see if we can satisfy the request from the freelist.
+ */
+ for (p = freelist, oldp = 0;
+ p && p != (struct chunk *)brkval;
+ oldp = p, p = p->next) {
+ if (p->len > nelems) {
+ /* chunk is larger, shorten, and return the tail */
+ p->len -= nelems;
+ q = p + p->len;
+ q->next = 0;
+ q->len = nelems;
+ q++;
+ return (void *)q;
+ }
+ if (p->len == nelems) {
+ /* exact match, remove from freelist */
+ if (oldp == 0)
+ freelist = p->next;
+ else
+ oldp->next = p->next;
+ p->next = 0;
+ p++;
+ return (void *)p;
+ }
+ }
+ /*
+ * Nothing found on freelist, try obtaining more space.
+ */
+ if (brkval == 0)
+ brkval = &end;
+ q = p = (struct chunk *)brkval;
+ if ((int)(p + NCHUNKS) > MAXBRK)
+ return 0;
+
+ p += NCHUNKS;
+ brkval = p;
+
+ q->next = p;
+ q->len = NCHUNKS;
+
+ if (oldp == 0)
+ freelist = q;
+ else {
+ if (oldp + oldp->len == q) {
+ /* extend last chunk */
+ oldp->len += NCHUNKS;
+ oldp->next = p;
+ } else
+ oldp->next = q;
+ }
+
+ return malloc(len);
+}
+
+void
+free(void *ptr)
+{
+ struct chunk *p, *q, *oldp;
+
+ if (ptr == 0)
+ return;
+
+ q = (struct chunk *)ptr;
+ q--;
+ if (q->next != 0) {
+ printf("malloc error: botched ptr to free()\n");
+ return;
+ }
+
+ /*
+ * Walk the freelist, and insert in the correct sequence.
+ */
+ for (p = freelist, oldp = 0;
+ p && p != (struct chunk *)brkval;
+ oldp = p, p = p->next) {
+ if ((unsigned)p > (unsigned)q) {
+ if (q + q->len == p) {
+ /* aggregate with next chunk */
+ q->len += p->len;
+ q->next = p->next;
+ p = p->next;
+ }
+ if (oldp) {
+ if (oldp + oldp->len == q) {
+ /* aggregate with previous chunk */
+ oldp->len += q->len;
+ oldp->next = p;
+ } else {
+ /* insert into chain */
+ q->next = p;
+ oldp->next = q;
+ }
+ return;
+ }
+ q->next = p;
+ freelist = q;
+ }
+ }
+ if (oldp) {
+ /* we are topmost */
+ if (oldp + oldp->len == q) {
+ /* aggregate with previous chunk */
+ oldp->len += q->len;
+ oldp->next = p;
+ } else {
+ oldp->next = q;
+ q->next = p;
+ }
+ return;
+ }
+ /* we are alone on the freelist */
+ freelist = q;
+}
+
OpenPOWER on IntegriCloud