makefs: make the buffer functions look exactly like the kernel ones

From NetBSD christos Sat Jan 26 00:19:39 2013 +0000

make the buffer functions look exactly like the kernel ones and add other
cruft to make the kernel files compile.

ffs.c 1.54
ffs/buf.c 1.13
ffs/buf.h 1.3
ffs/ffs_alloc.c 1.21
ffs/ffs_balloc.c 1.15

Reviewed by:	marcel, ngie
Obtained from:	NetBSD
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D8404
This commit is contained in:
Ed Maste 2017-02-11 02:33:48 +00:00
parent 9fc7a59f2a
commit 78b11a5903
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313575
52 changed files with 9600 additions and 61 deletions

5
sys/boot/pc98/Makefile Normal file
View File

@ -0,0 +1,5 @@
# $FreeBSD$
SUBDIR= boot0 boot0.5 pc98boot btx boot2 cdboot kgzldr libpc98 loader
.include <bsd.subdir.mk>

View File

@ -0,0 +1,29 @@
# Common defines for all of /sys/boot/pc98/
#
# $FreeBSD$
BINDIR?= /boot
LOADER_ADDRESS?=0x200000
CFLAGS+= -march=i386 -ffreestanding
CFLAGS.gcc+= -mpreferred-stack-boundary=2
CFLAGS+= ${CFLAGS_NO_SIMD} -msoft-float
CFLAGS+= -Os -DPC98
LDFLAGS+= -nostdlib
# BTX components
.if exists(${.OBJDIR}/../btx)
BTXDIR= ${.OBJDIR}/../btx
.else
BTXDIR= ${.CURDIR}/../btx
.endif
BTXLDR= ${BTXDIR}/btxldr/btxldr
BTXKERN= ${BTXDIR}/btx/btx
BTXCRT= ${BTXDIR}/lib/crt0.o
# compact binary with no padding between text, data, bss
LDSCRIPT= ${SRCTOP}/sys/boot/i386/boot.ldscript
LDFLAGS_BIN=-e start -Ttext ${ORG} -Wl,-T,${LDSCRIPT},-S,--oformat,binary
LD_FLAGS_BIN=-static -T ${LDSCRIPT} --gc-sections
.include "../Makefile.inc"

View File

@ -0,0 +1,26 @@
# $FreeBSD$
PROG= ${BOOT}.out
INTERNALPROG=
FILES= ${BOOT}
MAN=
SRCS= start.s boot.s boot0.5.s disk.s selector.s support.s syscons.s \
putssjis.s
CLEANFILES= ${BOOT} ${BOOT}.bin
BOOT= boot0.5
# The base address that we the boot0 code to to run it. Don't change this
# unless you are glutton for punishment.
BOOT_BOOT0_ORG?= 0x0000
LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} -Wl,-N,-T,${.CURDIR}/ldscript
# The size of boot0.5 must be 7168 bytes
${BOOT}: ${BOOT}.bin
cat ${BOOT}.bin /dev/zero | ${DD} of=${BOOT} bs=1 count=7168
${BOOT}.bin: ${BOOT}.out
${OBJCOPY} -S -O binary ${BOOT}.out ${.TARGET}
.include <bsd.prog.mk>

View File

@ -0,0 +1,174 @@
# Copyright (c) KATO Takenori, 1999, 2000.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.text
.global boot
#
# Read bootstrap program and jump to it.
#
boot:
# Step 1: Save parameters
movw curdevice, %si
movb daua(%si), %al
movb %al, b_daua
shlw %si
movw secsize(%si), %ax
movw %ax, b_secsize
movw curpartition, %si
movb partnum(%si), %al # %al = real partition number
xorb %ah, %ah
movw %ax, b_partn # save real parttion number
movb $5, %cl
shlw %cl, %si # %si = offset to parttable
addw $4, %si
movb parttable(%si), %al # IPLS
movb %al, b_sector
incw %si
movb parttable(%si), %al # IPLH
movb %al, b_head
incw %si # IPLC
movw parttable(%si), %ax
movw %ax, b_cylinder
# Step 2: Calculate the segment address of the bootstrap routine
movw $0x1d00, %ax
movw b_secsize, %cx
shrw %cx
shrw %cx
subw %cx, %ax
subw $0x100, %ax
movw %ax, b_bootseg
# Step 3: Read bootstrap code
movb $6, %ah
movb b_daua, %al
movw b_secsize, %bx
shlw %bx # 2 sectors
movw b_cylinder, %cx
movb b_head, %dh
movb b_sector, %dl
movw b_bootseg, %es
xorw %bp, %bp
int $0x1b
jc boot_error
# Step 4: Set DA/UA into BIOS work area
xorw %ax, %ax
movw %ax, %es
movw $0x584, %bx # DISK_BOOT
movb b_daua, %dl
call write_biosparam
call sc_clean
# Step 5: Set registers
# %ah: 00
# %al: DA/UA
# %bx: Sector size * 2
# %cx: cylinder number of boot partition
# %si: pointer to partition table
movw b_partn, %ax
movb $5, %cl
shl %cl, %ax # %ax = partition number * 32
addw b_secsize, %ax
movw %ax, %si # %si = pointer to partition table
movw b_cylinder, %cx # %cx = cylinder
movb b_head, %dh # %dh = head
movb b_sector, %dl # %dl = sector
movw b_bootseg, %es # %es = boot segment
movb b_daua, %al # %al = DA/UA
movw b_secsize, %bx
shlw %bx # %bx = sector size * 2
cli
movw %cs:iniss, %ss # Restore stack pointer
movw %cs:inisp, %sp
push %es # Boot segment
xorw %bp, %bp
push %bp # 0
movw %ax, %di # Save %ax
xorw %ax, %ax
movw %ax, %ds # %ds = 0
movw %di, %ax # Restore %ax
xorb %ah, %ah # %ah = 0
xorw %di, %di # %di = 0
sti
# Jump to bootstrap code
lret
# NOTREACHED
boot_error:
ret
#
# Try to boot from default partition.
#
.global trydefault
trydefault:
movw ndevice, %cx
xorw %si, %si
trydefault_loop:
movw %si, curdevice
push %cx
push %si
call read_ipl
pop %si
pop %cx
cmpb $0x80, defpartflag
jne nodefpart
# Default partition is defined.
push %cx
movw npartition, %cx
srch_part:
movw %cx, %bx
decw %bx
movb defpartnum, %al # %al = real partition number
cmpb partnum(%bx), %al
jne not_match
movw %bx, curpartition # Store partition number
call boot
not_match:
loop srch_part
pop %cx
nodefpart:
incw %si
loop trydefault_loop
ret
.data
b_daua: .byte 0 # DA/UA
b_head: .byte 0 # SYSH
b_sector: .byte 0 # SYSS
b_cylinder: .word 0 # SYSC
b_bootseg: .word 0
b_secsize: .word 0
b_partn: .word 0 # Real partition number

View File

@ -0,0 +1,293 @@
# Copyright (c) KATO Takenori, 1999, 2000, 2007.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.global main
.code16
.text
main:
# Check hireso mode
movw $0x501, %bx # BIOS_FLAG
call read_biosparam
testb $0x08, %dl
jz normalmode
movb $1, ishireso
normalmode:
call sc_init
# Display title and copyright.
movw $title, %di
call sc_puts
xorw %cx, %cx
movw $1, %dx
call sc_goto
movw $copyright, %di
call sc_puts
# Scan hard drives
xorw %si, %si # number of partition
call scan_sasi # SASI/IDE
call scan_scsi # SCSI
movw %si, ndevice
orw %si, %si
jnz drives_found
jmp exit # No hard drives
drives_found:
# Setup sector size dependent parameters
movw %si, %cx # %cx = number of devices
setup_loop:
movw %cx, %di
decw %di
shlw %di
movw secsize(%di), %ax
cmpw $1024, %ax
je setup_1024
cmpw $512, %ax
je setup_512
# 256 bytes/sector
movw $0x100, partoff(%di)
movw $0x0fa, defflagoff(%di)
movw $0x0fb, defpartoff(%di)
movw $8, maxpart(%di)
jmp setup_secsize_end
# 1024 bytes/sector
setup_1024:
# XXX Fix me!
movw $0x400, partoff(%di)
movw $0x3fa, defflagoff(%di)
movw $0x3fb, defpartoff(%di)
movb $32, maxpart(%di)
jmp setup_secsize_end
# 512 bytes/sector
setup_512:
movw $0x200, partoff(%di)
movw $0x1fa, defflagoff(%di)
movw $0x1fb, defpartoff(%di)
movb $16, maxpart(%di)
setup_secsize_end:
loop setup_loop
# For debug with floppy, fake the parameter.
movw $0x584, %bx # DISK_BOOT
call read_biosparam
andb $0xf0, %dl
cmpb $0x90, %ah
jne boot_from_hdd
movb daua, %dl
call write_biosparam
boot_from_hdd:
movw $500, %cx
wait_0_5:
call wait1ms
loop wait_0_5
# If the TAB is pressed, don't try to boot from default partition
xorw %di, %di # flag
wait_key_release:
call sc_iskeypress
orw %ax, %ax
jz key_release # KBD buffer empty.
call sc_getc
cmpb $0x0f, %ah # TAB
jne wait_key_release
# TAB pressed
movw $1, %di
jmp wait_key_release
key_release:
orw %di, %di
jnz dont_try_default # TAB pressed.
call trydefault
# Default partition not found.
dont_try_default:
call show_usage
call showdevices
call selector
exit:
ret
#
# Display usage
#
show_usage:
movw $44, %cx
movw $3, %dx
call sc_goto
movw $msg_usage1, %di
call sc_puts
movw $44, %cx
movw $4, %dx
call sc_goto
movw $msg_usage2, %di
call sc_puts
movw $44, %cx
movw $5, %dx
call sc_goto
movw $msg_usage3, %di
call sc_puts
movw $44, %cx
movw $7, %dx
call sc_goto
movw $msg_usage4, %di
call sc_puts
movw $44, %cx
movw $8, %dx
call sc_goto
movw $msg_usage5, %di
call sc_puts
movw $44, %cx
movw $9, %dx
call sc_goto
movw $msg_usage6, %di
call sc_puts
movw $44, %cx
movw $10, %dx
call sc_goto
movw $msg_usage7, %di
call sc_puts
movw $44, %cx
movw $11, %dx
call sc_goto
movw $msg_usage8, %di
call sc_puts
movw $44, %cx
movw $16, %dx
call sc_goto
movw $msg_usage9, %di
call sc_puts
movw $44, %cx
movw $17, %dx
call sc_goto
movw $msg_usage10, %di
call sc_puts
movw $44, %cx
movw $18, %dx
call sc_goto
movw $msg_usage11, %di
call sc_puts
movw $44, %cx
movw $19, %dx
call sc_goto
movw $msg_usage12, %di
call sc_puts
ret
#
# Display device list
#
showdevices:
movw $2, %cx
movw $4, %dx
call sc_goto
movw $msg_device, %di
call sc_puts
xorw %si, %si # %si = device number
movw ndevice, %cx # %cx = number of devices
showdev_loop:
push %cx
movw $2, %cx
movw $5, %dx
addw %si, %dx
call sc_goto
# Check DA
movb daua(%si), %al
push %ax
andb $0xf0, %al
cmpb $0x80, %al
je show_sasi
cmpb $0xa0, %al
je show_scsi
# unknown device
movw $msg_unknown, %di
call sc_puts
jmp showunit
# SASI
show_sasi:
movw $msg_sasi, %di
call sc_puts
jmp showunit
# SCSI
show_scsi:
movw $msg_scsi, %di
call sc_puts
# Display unit number.
showunit:
pop %ax
andb $0x0f, %al
addb $'0', %al
call sc_putc
incw %si
pop %cx
loop showdev_loop
movw ndevice, %dx
addw $5, %dx
movw $2, %cx
call sc_goto
movw $msg_exitmenu, %di
call sc_puts
ret
.data
.global curdevice, ndevice
ndevice: .word 0 # number of device
curdevice: .word 0 # current device
.global ishireso
ishireso: .byte 0
title: .asciz "PC98 Boot Selector Version 1.2"
copyright: .ascii "(C)Copyright 1999-2007 KATO Takenori. "
.asciz "All rights reserved."
msg_device: .asciz "Device"
msg_sasi: .asciz "SASI/IDE unit "
msg_scsi: .asciz "SCSI ID "
msg_unknown: .asciz "unknown unit "
msg_exitmenu: .asciz "Exit this menu"
msg_usage1: .asciz "Device list"
msg_usage2: .asciz "UP, DOWN: select boot device"
msg_usage3: .asciz "RETURN: move to slice list"
msg_usage4: .asciz "Slice list"
msg_usage5: .asciz "UP, DOWN: select boot slice"
msg_usage6: .asciz "RETURN: boot"
msg_usage7: .asciz "SPACE: toggle default"
msg_usage8: .asciz "ESC: move to device list"
msg_usage9: .asciz "LEGEND"
msg_usage10: .asciz ">>: selected device/slice"
msg_usage11: .asciz "*: default slice to boot"
msg_usage12: .asciz "!: unbootable slice"
.bss
.global daua, secsize, defflagoff, defpartoff
.global maxpart, partoff
daua: .space 12 # DA/DU list
secsize: .space 12 * 2 # Sector soize
defflagoff: .space 12 * 2
defpartoff: .space 12 * 2
maxpart: .space 12 * 2
partoff: .space 12 * 2

View File

@ -0,0 +1,296 @@
# Copyright (c) KATO Takenori, 1999, 2000.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.text
#
# Check magic number at the end of the sector 0
#
check_magic:
movw curdevice, %si
shlw %si
movw secsize(%si), %bx
decw %bx
decw %bx
movw iplbuf(%bx), %ax
cmpw $0xaa55, %ax
je magic_ok
movw $1, %ax
ret
magic_ok:
xorw %ax, %ax
ret
#
# Copy partition table from buffer to parttable.
#
setup_partition:
push %cs
pop %es
movw curdevice, %bx
shlw %bx
movw maxpart(%bx), %cx # %cx = max num of partitions
movw partoff(%bx), %di
movw %di, %bx # %bx = offset to partition table
xorw %dx, %dx # %dx = partition number
setup_partition_loop:
push %cx
movw %dx, %si
movb $5, %cl
shlw %cl, %si
addw %bx, %si
movb iplbuf(%si), %al
orb %al, %al
jz unused_partition
addw $iplbuf, %si
movw npartition, %ax
movw %ax, %di
movb $5, %cl
shlw %cl, %di
addw $parttable, %di
movw $32, %cx
rep
movsb
movw %ax, %di
addw $partnum, %di
movb %dl, (%di)
incw npartition
unused_partition:
incw %dx
pop %cx
loop setup_partition_loop
ret
#
# Read IPL and partition table in the current device.
#
.global read_ipl
read_ipl:
movw curdevice, %ax
movw %ax, %si # %si = device number
movw %ax, %di
shlw %di
movw %cs, %ax
movw %ax, %es
movb $6, %ah
movb daua(%si), %al
movw $0x400, %bx
xorw %cx, %cx
xorw %dx, %dx
movw $iplbuf, %bp
int $0x1b
jc read_ipl_error
movw defflagoff(%di), %bx
movb iplbuf(%bx), %al
movb %al, defpartflag
incw %bx
movb iplbuf(%bx), %al
movb %al, defpartnum
movw $0, npartition
call check_magic
orw %ax, %ax
jnz no_magic
call setup_partition
no_magic:
xorw %ax, %ax
read_ipl_error:
xorw %bx, %bx
movw %bx, %es
ret
#
# Restore IPL from the buffer
#
.global write_ipl
write_ipl:
movw curdevice, %ax
movw %ax, %si
movw %ax, %di
shlw %di
# Restore default boot partition info.
movw defflagoff(%di), %bx
movb defpartflag, %al
movb %al, iplbuf(%bx)
incw %bx
movb defpartnum, %al
movb %al, iplbuf(%bx)
movw %cs, %ax
movw %ax, %es
movb $5, %ah
movb daua(%si), %al
movw secsize(%di), %bx
xorw %cx, %cx
xorw %dx, %dx
movw $iplbuf, %bp
int $0x1b
jc write_ipl_error
xorw %ax, %ax
write_ipl_error:
xorw %bx, %bx
movw %bx, %es
ret
#
# Scan HDD devices
#
.global scan_sasi, scan_scsi
# Scan SASI disk
scan_sasi:
# SASI Disk
movw $4, %cx
movw $0x0001, %ax # %ah = unit number, %al = for bit operation
sasi_loop:
movw %si, %di
shlw %di
movw $0x55d, %bx # DISK_EQUIP
call read_biosparam
testb %al, %dl
jz no_sasi_unit
movb $0x80, %dh
addb %ah, %dh # %dh = DA/UA
movb %dh, daua(%si) # Store DA/UA
# Try new sense command
push %ax
push %cx
movb %dh, %al
movb $0x84, %ah
int $0x1b
pop %cx
pop %ax
jc err_newsense
movw %bx, %dx
jmp found_sasi_unit
err_newsense:
movw $0x457, %bx # capacity & sector size of IDE HDD
call read_biosparam
orb %ah, %ah
jz sasi_1
cmpb $1, %ah
jz sasi_2
# SASI #3/#4
movw $512, %dx # XXX
jmp found_sasi_unit
sasi_1:
# SASI #1
testb $0x80, %dl
jz sasi_256
jmp sasi_512
sasi_2:
# SASI #2
testb $0x40, %dl
jz sasi_256
jmp sasi_512
sasi_256:
movw $256, %dx
jmp found_sasi_unit
sasi_512:
movw $512, %dx
found_sasi_unit:
movw %dx, secsize(%di)
incw %si
no_sasi_unit:
incb %ah
shlb %al
loop sasi_loop
ret
#
# Scan SCSI disk
# SI number of disks
# destroyed: %ax, %bx, %cx, %dx
scan_scsi:
movw $8, %cx
movw $0x0001, %ax # %ah = ID number, %al = for bit operation
scsi_loop:
# Check whether drive exist.
movw %si, %di
shlw %di
movw $0x482, %bx # DISK_EQUIPS
call read_biosparam
testb %al, %dl
jz no_scsi_unit
xorw %bx, %bx
movb %ah, %bl
shlw %bx
shlw %bx
addw $0x460, %bx # SCSI parameter block
call read_biosparam
orb %dl, %dl
jz no_scsi_unit
# SCSI harddrive found.
movb $0xa0, %dh
addb %ah, %dh
movb %dh, daua(%si)
# Check sector size.
addw $3, %bx
call read_biosparam
andb $0x30, %dl
cmpb $0x20, %dl
je scsi_1024
cmpb $0x10, %dl
je scsi_512
movw $256, %dx
jmp found_scsi
scsi_1024:
movw $1024, %dx
jmp found_scsi
scsi_512:
movw $512, %dx
found_scsi:
movw %dx, secsize(%di)
incw %si
no_scsi_unit:
incb %ah
shlb %al
loop scsi_loop
ret
.data
.global defpartflag, defpartnum, npartition
defpartflag: .byte 0
defpartnum: .byte 0
npartition: .word 0 # number of partitions
.bss
.global partnum, parttable
iplbuf: .space 0x400 # Read buffer for IPL
partnum: .space 32 # Index of parttable
parttable: .space 1024 # Copy of valid partition table

View File

@ -0,0 +1,12 @@
/*
* $FreeBSD$
*/
SECTIONS
{
.text : { *(.text) }
.data : { *(.data) }
. = 0x1243;
.putssjis : { *(.putssjis) }
.bss : { *(.bss) }
}

View File

@ -0,0 +1,137 @@
# Copyright (c) KATO Takenori, 2007.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.section .putssjis, "awx", @progbits
#
# Display string with Shift-JIS support
# %si: address of string, %di: T-VRAM address, %cx: count
#
# Absolute address of putssjis_entry must be 0x1243.
putssjis_entry:
push %es
push %ax
# Setup the T-VRAM segement address.
xorw %ax, %ax
movw %ax, %es
movw $0xa000, %ax
testb $0x08, %es:0x501
jz normalmode
movw $0xe000, %ax
normalmode:
movw %ax, %es
putssjis_loop:
lodsw
call check_sjis
jc put_2byte_char
# 1 byte character
xorb %ah, %ah
testb $0xe0, %al # Check control code.
jnz put_1byte_char
movb $0x20, %al # Convert control code into the space.
put_1byte_char:
stosw
decw %si
jmp putssjis_loop_end
put_2byte_char:
subb $0x20, %al
# Check 2byte "hankaku"
cmp $0x09, %al
je put_2byte_hankaku
cmp $0x0a, %al
je put_2byte_hankaku
cmp $0x0b, %al
je put_2byte_hankaku
jmp put_2byte_zenkaku
put_2byte_hankaku:
stosw
jmp putssjis_loop_end
put_2byte_zenkaku:
stosw
orb $0x80, %ah
stosw
decw %cx
putssjis_loop_end:
loop putssjis_loop
pop %ax
pop %es
ret
# Check 2-byte code.
check_sjis:
cmpb $0x80, %al
jbe found_ank_kana
cmpb $0xa0, %al
jb found_2byte_char
cmpb $0xe0, %al
jb found_ank_kana
cmpb $0xf0, %al
jae found_ank_kana
jmp found_2byte_char
found_ank_kana:
clc
ret
found_2byte_char:
# Convert Shift-JIS into JIS.
cmpb $0x9f, %al
ja sjis_h_2 # Upper > 0x9f
subb $0x71, %al # Upper -= 0x71
jmp sjis_lower
sjis_h_2:
subb $0xb1, %al # Upper -= 0xb1
sjis_lower:
salb %al # Upper *= 2
incb %al # Upper += 1
cmpb $0x7f, %ah
jbe sjis_l_2
decb %ah # Lower -= 1 if lower > 0x7f
sjis_l_2:
cmpb $0x9e, %ah
jb sjis_l_3
subb $0x7d, %ah # Lower -= 0x7d
incb %al # Upper += 1
jmp check_2byte_end
sjis_l_3:
subb $0x1f, %ah # Lower -= 0x1f
check_2byte_end:
stc
ret

View File

@ -0,0 +1,450 @@
# Copyright (c) KATO Takenori, 1999, 2000, 2007.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.text
#
# Display partition table.
#
showpartitions:
# Clear partition table area
movw $16, %cx
clear_part:
push %cx
movw %cx, %dx
decw %dx
addw $5, %dx
movw $20, %cx
call sc_goto
movw $msg_spc, %di
call sc_puts
pop %cx
loop clear_part
# Check `Exit' menu
movw curdevice, %ax
cmpw ndevice, %ax
je no_slice
# XXX Move this to a suitable place!
movw $22, %cx
movw $4, %dx
call sc_goto
movw $msg_slice, %di
call sc_puts
# Check the number of partitions
movw npartition, %cx
orw %cx, %cx
jnz partitionexist
no_slice:
# Just show the `no slice' message.
movw $22, %cx
movw $5, %dx
call sc_goto
movw $msg_noslice, %di
call sc_puts
ret
partitionexist:
xorw %si, %si # %si = partition number
showpart_loop:
push %cx # %cx = number of partitions
movw $22, %cx
movw %si, %dx
addw $5, %dx
call sc_goto
movw %si, %di
movb $5, %cl
shlw %cl, %di
addw $0x10, %di # SYSM field
# SYSM: space filled string. Don't use sc_puts.
movw $16, %cx
showpart_name:
push %cx
movb parttable(%di), %al
call sc_putc
incw %di
pop %cx
loop showpart_name
incw %si
pop %cx
loop showpart_loop
ret
#
# Show default slice indicator
# If the default boot slice exists, `*' indicator will be showed.
#
showdefaultslicemark:
cmpb $0x80, defpartflag
je defpartexist
ret
defpartexist:
movw npartition, %cx
defslice_loop:
movw %cx, %bx
decw %bx
push %cx
push %bx
movw $40, %cx
movw %bx, %dx
addw $5, %dx
call sc_goto
pop %bx
pop %cx
movb defpartnum, %al
cmpb partnum(%bx), %al
jne nomatch
movb $'*', %al
call sc_putc
jmp defslice_done
nomatch:
movb $' ', %al
call sc_putc
defslice_done:
loop defslice_loop
ret
#
# Hide default slice indicator
#
hidedefaultslicemark:
movw $16, %cx
hidedefslice_loop:
push %cx
movw %cx, %dx
addw $4, %dx
movw $40, %cx
call sc_goto
movb $' ', %al
call sc_putc
pop %cx
loop hidedefslice_loop
ret
#
# Toggle default slice
#
toggle_default:
cmpb $0x80, defpartflag
jne set_default
# Clear default
movb $0, defpartflag
call write_ipl # Restore
call hidedefaultslicemark
ret
# Set default slice
set_default:
movw curpartition, %si
movb partnum(%si), %al # %al = real partition number
movb $5, %cl
shlw %cl, %si
# Default slice must be bootable
testb $0x80, parttable(%si)
jnz curpart_bootable
# Current partition is not bootable.
ret
curpart_bootable:
movb $0x80, defpartflag
movb %al, defpartnum
call write_ipl # Restore
call showdefaultslicemark
ret
#
# Show/hide cursor
#
show_devcurs:
xorw %cx, %cx
movw curdevice, %dx
addw $5, %dx
call sc_goto
movb $'>', %al
call sc_putc
movb $'>', %al
call sc_putc
ret
hide_devcurs:
xorw %cx, %cx
movw curdevice, %dx
addw $5, %dx
call sc_goto
movb $' ', %al
call sc_putc
movb $' ', %al
call sc_putc
ret
show_slicecurs:
movw $20, %cx
movw curpartition, %dx
addw $5, %dx
call sc_goto
movb $'>', %al
call sc_putc
movb $'>', %al
call sc_putc
ret
hide_slicecurs:
movw $20, %cx
movw curpartition, %dx
addw $5, %dx
call sc_goto
movb $' ', %al
call sc_putc
movb $' ', %al
call sc_putc
ret
isforceboot:
xorw %cx, %cx
movw $20, %dx
call sc_goto
movw $msg_force, %di
call sc_puts
call sc_getc
push %ax
xorw %cx, %cx
movw $20, %dx
call sc_goto
movw $msg_forceclr, %di
call sc_puts
pop %ax
cmpb $0x15, %ah
je force_yes
xorw %ax, %ax
ret
force_yes:
movw $1, %ax
ret
#
# Main loop for device mode
#
devmode:
call read_ipl
call hidedefaultslicemark
call showpartitions
call showdefaultslicemark
call show_devcurs
movw $2, %cx
movw $4, %dx
call sc_goto
movb $0xe5, %al
movw $6, %cx
call sc_setattr
movw $22, %cx
movw $4, %dx
call sc_goto
movb $0xe1, %al
movw $5, %cx
call sc_setattr
movw $44, %cx
movw $3, %dx
call sc_goto
movb $0xe5, %al
movw $11, %cx
call sc_setattr
movw $44, %cx
movw $7, %dx
call sc_goto
movb $0xe1, %al
movw $10, %cx
call sc_setattr
devmode_loop:
call sc_getc
movw ndevice, %bx
cmpb $0x3a, %ah # UP
je dev_up
cmpb $0x3d, %ah # DOWN
je dev_down
cmpb $0x3c, %ah # RIGHT
je dev_right
cmpb $0x1c, %ah # RETURN
jne devmode_loop
cmpw curdevice, %bx
jne dev_right
movw $3, mode # N88-BASIC
ret
# XXX
.space 5, 0x90
ret # Dummy ret @0x9ab
dev_up:
cmpw $0, curdevice
je devmode_loop
call hide_devcurs
decw curdevice
call read_ipl
call hidedefaultslicemark
call showpartitions
call showdefaultslicemark
call show_devcurs
jmp devmode_loop
dev_down:
cmpw curdevice, %bx
je devmode_loop
call hide_devcurs
incw curdevice
call read_ipl
call hidedefaultslicemark
call showpartitions
call showdefaultslicemark
call show_devcurs
jmp devmode_loop
dev_right:
cmpw curdevice, %bx
je devmode_loop
movw $1, mode # Slice mode
ret
#
# main loop for slice mode
#
slicemode:
movw $0, curpartition
call show_slicecurs
movw $2, %cx
movw $4, %dx
call sc_goto
movb $0xe1, %al
movw $6, %cx
call sc_setattr
movw $22, %cx
movw $4, %dx
call sc_goto
movb $0xe5, %al
movw $5, %cx
call sc_setattr
movw $44, %cx
movw $3, %dx
call sc_goto
movb $0xe1, %al
movw $11, %cx
call sc_setattr
movw $44, %cx
movw $7, %dx
call sc_goto
movb $0xe5, %al
movw $10, %cx
call sc_setattr
slicemode_loop:
call sc_getc
cmpb $0x3a, %ah # UP
je slice_up
cmpb $0x3d, %ah # DOWN
je slice_down
cmpb $0x3b, %ah # LEFT
je slice_esc
cmpb $0x00, %ah # ESC
je slice_esc
cmpb $0x1c, %ah # RETURN
je slice_ret
cmpb $0x34, %ah # SPC
je slice_spc
cmpb $0x62, %ah # f1
je slice_spc
jmp slicemode_loop
slice_up:
cmpw $0, curpartition
je slicemode_loop
call hide_slicecurs
decw curpartition
call show_slicecurs
jmp slicemode_loop
slice_down:
movw curpartition, %bx
movw npartition, %ax
decw %ax
cmpw %bx, %ax
je slicemode_loop
call hide_slicecurs
incw curpartition
call show_slicecurs
jmp slicemode_loop
slice_esc:
movw $0, mode # Device mode
ret
slice_spc:
call toggle_default
jmp slicemode_loop
slice_ret:
# Test bit 7 of mid
movw curpartition, %si
movb $5, %cl
shlw %cl, %si
testb $0x80, parttable(%si)
jnz bootable_slice
call isforceboot
orw %ax, %ax
jz slicemode_loop
bootable_slice:
call boot
jmp slicemode_loop
#
# Main loop
#
.global selector
selector:
movw $0, curdevice # trydefault may change the curdevice.
movw $0, mode
selector_loop:
cmpw $0, mode
je status_dev
cmpw $1, mode
je status_slice
ret
status_dev:
call devmode
jmp selector_loop
status_slice:
call slicemode
jmp selector_loop
.data
.global curpartition
curpartition: .word 0 # current patition
mode: .word 0
msg_spc: .asciz " "
msg_slice: .asciz "Slice"
msg_noslice: .asciz "no slice"
msg_force: .asciz "This slice is not bootable. Continue? (Y / [N])"
msg_forceclr: .asciz " "

View File

@ -0,0 +1,73 @@
# Copyright (c) KATO Takenori, 1999, 2000, 2007.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.global start
.code16
.text
start:
jmp start1
# Magic
.org 0x053, 0x20
.byte 0x4e, 0x45, 0x43
.org 0x8f
.byte 0x32, 0x2e, 0x37, 0x30
.org 0x2d4
start1:
# The instruction 'call 0x9ab' can be here. See also selector.s.
nop
nop
nop
cli
movw %cs, %ax
movw %ax, %ds
movw %ss, iniss
movw %sp, inisp
movw %ax, %ss
movw $0xfffe, %sp
sti
xorw %ax, %ax
movw %ax, %es
call main
cli
movw %cs:iniss, %ss
movw %cs:inisp, %sp
sti
int $0x1e
# NOTREACHED
lret
.data
.global iniss, inisp
iniss: .word 0
inisp: .word 0

View File

@ -0,0 +1,94 @@
# Copyright (c) KATO Takenori, 1999, 2000.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.text
#
# Wait 1ms
#
.global wait1ms
wait1ms:
push %cx
movw $800, %cx
wait_loop:
outb %al, $0x5f
loop wait_loop
pop %cx
ret
#
# Read one byte from BIOS parameter block
# %bx offset
# %dl value
#
.global read_biosparam
read_biosparam:
movb %es:(%bx), %dl
ret
#
# Write one byte to BIOS parameter block
# %bx offset
# %dl value
#
.global write_biosparam
write_biosparam:
movb %dl, %es:(%bx)
ret
#
# beep
#
.global beep_on, beep_off, beep
beep_on:
movb $0x17, %ah
int $0x18
ret
beep_off:
movb $0x18, %ah
int $0x18
ret
beep:
push %cx
call beep_on
movw $100, %cx
beep_loop1:
call wait1ms
loop beep_loop1
call beep_off
movw $50, %cx
beep_loop2:
call wait1ms
loop beep_loop2
pop %cx
ret

View File

@ -0,0 +1,253 @@
# Copyright (c) KATO Takenori, 1999, 2000.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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.
#
# $FreeBSD$
#
.code16
.text
#
# %al character code
# destroyed: %al, %bx
#
put_character:
movw $0xe000, %bx
movb ishireso, %ah
orb %ah, %ah
jne hireso_ch
movw $0xa000, %bx
hireso_ch:
movw %bx, %es
xorb %ah, %ah
movw curpos, %bx
movw %ax, %es:(%bx)
xorw %ax, %ax
movw %ax, %es
ret
#
# %al attribute
# destroyed: %ah, %cx
#
set_attribute:
movw $0xe200, %bx
movb ishireso, %ah
orb %ah, %ah
jne hireso_ch
movw $0xa200, %bx
hireso_attr:
movw %bx, %es
xorb %ah, %ah
movw curpos, %bx
movw %ax, %es:(%bx)
xorw %bx, %bx
movw %bx, %es
ret
#
# Put a character
# %al: character code
# destroyed: %ah, %bx, %cx
#
.global sc_putc
sc_putc:
call put_character
incw curpos
incw curpos
cmpw $4000, curpos
jng putc_end
movw $0, curpos
putc_end:
ret
#
# Put a null terminated string
# %di: pointer to string
# destroyed: %ah, %cx, %di
#
.global sc_puts
sc_puts:
movb (%di), %al
orb %al, %al
jz puts_end
call sc_putc
incw %di
jmp sc_puts
puts_end:
ret
#
# Change the current cursor position
# %cx: X
# %dx: Y
# destroyed: %ax, %bx
#
.global sc_goto
sc_goto:
movw %dx, %ax # AX=Y
shlw %ax # AX=Y*64
shlw %ax
shlw %ax
shlw %ax
shlw %ax
shlw %ax
movw %dx, %bx # BX=Y
shlw %bx # BX=Y*16
shlw %bx
shlw %bx
shlw %bx
addw %bx, %ax # AX=Y*64+Y*16=Y*80
addw %cx, %ax
shlw %ax
movw %ax, curpos
ret
#
# Clear screen
# destroyed: %ax, %bx
#
.global sc_clean
sc_clean:
movb $0x16, %ah
movw $0xe120, %dx
int $0x18 # KBD/CRT BIOS
movw $0, curpos
ret
#
# Set sttribute code
# %al: attribute
# %cx: count
# destroyed: %ax, %bx, %cx
#
.global sc_setattr
sc_setattr:
call set_attribute
incw curpos
incw curpos
loop sc_setattr
#
# Sense the state of shift key
# destroyed: %ax
#
.global sc_getshiftkey
sc_getshiftkey:
movb $2, %ah # Sense KB_SHIFT_COD
int $0x18 # KBD/CRT BIOS
xorb %ah, %ah
ret
#
# Check KBD buffer
#
.global sc_iskeypress
sc_iskeypress:
mov $1, %ah
int $0x18 # KBD/CRT BIOS
testb $1, %bh
jz no_key
movw $1, %ax
ret
no_key:
xorw %ax, %ax
ret
#
# Read from KBD
#
.global sc_getc
sc_getc:
xorb %ah, %ah
int $0x18
ret
#
# Initialize CRT (normal mode)
#
init_screen_normal:
# Disable graphic screen
movb $0x41, %ah
int $0x18
# Init graphic screen
movb $0x42, %al
movb $0xc0, %ch
int $0x18
# 80x25 mode
movw $0x0a00, %ax
int $0x18
ret
#
# Initialize CRT (hireso mode)
#
init_screen_hireso:
# Init RAM window
movb $8, %al
outb %al, $0x91
movb $0x0a, %al
outb %al, $0x93
# 80x31 mode
movw $0x0a00, %ax
int $0x18
ret
#
# Initialize screen (internal)
#
init_screen:
movb ishireso, %ah
orb %ah, %ah
jne hireso_ini
call init_screen_normal
jmp init_next
hireso_ini:
call init_screen_hireso
init_next:
movb $0x0c, %ah
int $0x18
# cursor home and off
xorw %dx, %dx
movb $0x13, %ah
int $0x18
movb $0x12, %ah
int $0x18
ret
#
# Initialize screeen
#
.global sc_init
sc_init:
call init_screen
call sc_clean
movw $0, curpos
ret
.data
curpos: .word 0 # Current cursor position

View File

@ -0,0 +1,19 @@
# $FreeBSD$
PROG= ${BOOT}
INTERNALPROG=
FILES= ${BOOT}
MAN=
SRCS= ${BOOT}.s
CLEANFILES= ${BOOT}
BOOT= boot0
# The base address that we the boot0 code to to run it. Don't change this
# unless you are glutton for punishment.
BOOT_BOOT0_ORG?= 0x0000
ORG=${BOOT_BOOT0_ORG}
LDFLAGS=${LDFLAGS_BIN}
.include <bsd.prog.mk>

108
sys/boot/pc98/boot0/boot0.s Normal file
View File

@ -0,0 +1,108 @@
# Copyright (c) KATO Takenori, 1999, 2000.
#
# All rights reserved. Unpublished rights reserved under the copyright
# laws of Japan.
#
# 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 as
# the first lines of this file unmodified.
# 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. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# 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.
#
# $FreeBSD$
.globl start
.code16
start:
jmp main
.org 4
.ascii "IPL1"
.byte 0, 0, 0
.globl start
main:
xor %ax, %ax
mov %ax, %ds
mov (0x584), %al # DA/UA
mov %al, %ah
and $0xf0, %ah
cmp $0x90, %ah
je fdd
# hdd
mov $6, %ah
mov $0x3000, %bx
mov %bx, %es
mov $0x2000, %bx
xor %cx, %cx
xor %dx, %dx
xor %bp, %bp
int $0x1b
jc error_hdd
push %ax
mov %es, %ax
add $0x40, %ax
mov %ax, %es
pop %ax
push %es
push %bp
lret
# fdd
fdd:
xor %di, %di
fdd_retry:
mov $0xd6, %ah
mov $0x3000, %bx
mov %bx, %es
mov $0x2000, %bx
mov $0x0200, %cx
mov $0x0001, %dx
xor %bp, %bp
int $0x1b
jc error
push %ax
mov %es, %ax
add $0x40, %ax
mov %ax, %es
pop %ax
push %es
push %bp
lret
error:
or %di, %di
jnz error_hdd
and $0x0f, %al
or $0x30, %al
jmp fdd_retry
error_hdd:
jmp error
.org 0x1fa
.byte 0 # defflag_off
.byte 0 # defpart_off
.byte 1 # menu version
.byte 0
.word 0xaa55

View File

@ -0,0 +1,116 @@
# $FreeBSD$
.include <bsd.own.mk>
FILES= boot boot1 boot2
NM?= nm
BOOT_COMCONSOLE_PORT?= 0x238
BOOT_COMCONSOLE_SPEED?= 9600
B2SIOFMT?= 0x3
REL1= 0x700
ORG1= 0
ORG2= 0x2000
# Decide level of UFS support.
BOOT2_UFS?= UFS1_AND_UFS2
#BOOT2_UFS?= UFS2_ONLY
#BOOT2_UFS?= UFS1_ONLY
CFLAGS= -fomit-frame-pointer \
-mrtd \
-mregparm=3 \
-D${BOOT2_UFS} \
-DFLAGS=${BOOT_BOOT1_FLAGS} \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
-DSIOSPD=${BOOT_COMCONSOLE_SPEED} \
-I${.CURDIR}/../../.. \
-I${.CURDIR}/../../i386/boot2 \
-I${.CURDIR}/../../common \
-I${.CURDIR}/../btx/lib -I. \
-Wall -Waggregate-return -Wbad-function-cast -Wcast-align \
-Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
-Winline
CFLAGS.gcc+= -Os \
-fno-guess-branch-probability \
-fno-unit-at-a-time \
--param max-inline-insns-single=100
.if ${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} <= 40201
CFLAGS.gcc+= -mno-align-long-strings
.endif
# Set machine type to PC98_SYSTEM_PARAMETER
#CFLAGS+= -DSET_MACHINE_TYPE
# Initialize the bi_bios_geom using the BIOS geometry
#CFLAGS+= -DGET_BIOSGEOM
CFLAGS.clang+= -Oz ${CLANG_OPT_SMALL}
LD_FLAGS=${LD_FLAGS_BIN}
# Pick up ../Makefile.inc early.
.include <bsd.init.mk>
.PATH: ${.CURDIR}/../../i386/boot2
CLEANFILES= boot
boot: boot1 boot2
cat boot1 boot2 > boot
CLEANFILES+= boot1 boot1.out boot1.o
boot1: boot1.out
${OBJCOPY} -S -O binary boot1.out ${.TARGET}
boot1.out: boot1.o
${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} boot1.o
CLEANFILES+= boot2 boot2.ld boot2.ldr boot2.bin boot2.out boot2.o \
boot2.s boot2.s.tmp boot2.h sio.o
boot2: boot2.ld
@set -- `ls -l boot2.ld`; x=$$((7680-$$5)); \
echo "$$x bytes available"; test $$x -ge 0
${DD} if=boot2.ld of=${.TARGET} obs=7680 conv=osync
boot2.ld: boot2.ldr boot2.bin ${BTXKERN}
btxld -v -E ${ORG2} -f bin -b ${BTXKERN} -l boot2.ldr \
-o ${.TARGET} -P 1 boot2.bin
boot2.ldr:
${DD} if=/dev/zero of=${.TARGET} bs=276 count=1
boot2.bin: boot2.out
${OBJCOPY} -S -O binary boot2.out ${.TARGET}
boot2.out: ${BTXCRT} boot2.o sio.o
${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
boot2.o: boot2.s
${CC} ${ACFLAGS} -c boot2.s
SRCS= boot2.c boot2.h
boot2.s: boot2.c boot2.h ${.CURDIR}/../../common/ufsread.c
${CC} ${CFLAGS} -S -o boot2.s.tmp ${.CURDIR}/boot2.c
sed -e '/align/d' -e '/nop/d' < boot2.s.tmp > boot2.s
rm -f boot2.s.tmp
boot2.h: boot1.out
${NM} -t d ${.ALLSRC} | awk '/([0-9])+ T (read|putc)/ \
{ x = $$1 - ORG1; \
printf("#define %sORG %#x\n", toupper($$3), REL1 + x) }' \
ORG1=`printf "%d" ${ORG1}` \
REL1=`printf "%d" ${REL1}` > ${.TARGET}
.include <bsd.prog.mk>
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.boot1.S= ${CLANG_NO_IAS}

395
sys/boot/pc98/boot2/boot1.S Normal file
View File

@ -0,0 +1,395 @@
/*-
* Copyright (c) 2008-2009 TAKAHASHI Yoshihiro
* 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.
*
* $FreeBSD$
*/
/* Memory Locations */
.set STACK_OFF,0x6000 # Stack offset
.set LOAD_SIZE,8192 # Load size
.set DAUA,0x0584 # DA/UA
.set MEM_REL,0x700 # Relocation address
.set MEM_ARG,0x900 # Arguments
.set MEM_BUF,0x8cec # Load area
.set MEM_BTX,0x9000 # BTX start
.set MEM_JMP,0x9010 # BTX entry point
.set MEM_USR,0xa000 # Client start
/* PC98 machine type from sys/pc98/pc98/pc98_machdep.h */
.set MEM_SYS, 0xa100 # System common area segment
.set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
.set EPSON_ID, 0x0624 # EPSON machine id
.set M_NEC_PC98, 0x0001
.set M_EPSON_PC98, 0x0002
.set M_NOT_H98, 0x0010
.set M_H98, 0x0020
.set M_NOTE, 0x0040
.set M_NORMAL, 0x1000
.set M_8M, 0x8000
/* Partition Constants */
.set PRT_OFF,0x1be # Partition offset
/* Misc. Constants */
.set SIZ_PAG,0x1000 # Page size
.set SIZ_SEC,0x200 # Sector size
.set NSECT,0x10
.globl start
.globl read
.globl putc
.code16
start: jmp main
boot_cyl: .org 4
.ascii "IPL1 "
main: cld
/* Setup the stack */
xor %si,%si
mov %si,%ss
mov $STACK_OFF,%sp
push %cx
/* Relocate ourself to MEM_REL */
push %cs
pop %ds
mov %si,%es
mov $MEM_REL,%di
mov $SIZ_SEC,%cx
rep
movsb
/* Transfer PC-9801 system common area */
xor %ax,%ax
mov %ax,%si
mov %ax,%ds
mov %ax,%di
mov $MEM_SYS,%ax
mov %ax,%es
mov $0x0600,%cx
rep
movsb
/* Transfer EPSON machine type */
mov $0xfd00,%ax
mov %ax,%ds
mov (0x804),%eax
and $0x00ffffff,%eax
mov %eax,%es:(EPSON_ID)
/* Set machine type to PC98_SYSTEM_PARAMETER */
#ifdef SET_MACHINE_TYPE
call set_machine_type
#else
mov $M_NEC_PC98+M_NOT_H98,%eax
mov %eax,%es:(PC98_MACHINE_TYPE)
#endif
/* Setup graphic screen */
mov $0x42,%ah /* 640x400 */
mov $0xc0,%ch
int $0x18
mov $0x40,%ah /* graph on */
int $0x18
/* Setup text screen */
mov $0x0a00,%ax /* 80x25 */
int $0x18
mov $0x0c,%ah /* text on */
int $0x18
mov $0x13,%ah /* cursor home */
xor %dx,%dx
int $0x18
mov $0x11,%ah /* cursor on */
int $0x18
/* Setup keyboard */
mov $0x03,%ah
int $0x18
pop %cx
/* bootstrap passes */
xor %edi,%edi
mov %di,%ds
mov %di,%es
mov %cs,%bx
cmp $0x1fe0,%bx
jz boot_fd
cmp $0x1fc0,%bx
jnz boot_hd
xor %cx,%cx
mov (DAUA),%al
and $0xf0,%al
cmp $0x30,%al
jz boot_fd
cmp $0x90,%al
jnz boot_hd
boot_fd: xor %cx,%cx
jmp boot_load
boot_hd: test %cx,%cx
jnz boot_load
mov %cs:(boot_cyl),%cx
boot_load: mov %cx,MEM_ARG /* Save cylinder number */
mov %cx,%di
xor %dx,%dx
mov $LOAD_SIZE,%bx
mov $MEM_BUF,%bp
push %cs
callw read
jc error
/* Transfer boot2.bin */
mov $MEM_BTX,%bx
mov 0xa(%bx),%si /* BTX size */
add %bx,%si /* start of boot2.bin */
mov $MEM_USR+SIZ_PAG*2,%di
mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx
sub %si,%cx
rep
movsb
/* Enable A20 */
xor %ax,%ax
outb %al,$0xf2
mov $0x02,%al
outb %al,$0xf6
/* Start BTX */
ljmp $0x0000,$MEM_JMP
/*
* Reads sectors from the disk.
* Call with:
*
* %bx - bytes to read
* %cx - cylinder
* %dh - head
* %dl - sector
* %edi - lba
* %es:(%bp) - buffer to read data into
*/
read: xor %ax,%ax
mov %ax,%ds
mov $0x06,%ah
mov (DAUA),%al
mov %ax,%si
and $0xf0,%al
cmp $0x30,%al /* 1.44MB FDD */
jz read_fd
cmp $0x90,%al /* 1MB FDD */
jz read_fd
cmp $0xa0,%al /* Is SCSI device? */
jnz read_load
push %cx
mov %si,%cx
and $0x0f,%cl
inc %cl
mov (0x482),%ah
shr %cl,%ah /* Is SCSI HDD? */
pop %cx
jc read_load
and $0xff7f,%si /* SCSI MO */
mov %di,%cx
shr $16,%edi
mov %di,%dx
jmp read_load
read_fd: or $0xd000,%si
or $0x0200,%cx
inc %dx
read_load: mov %si,%ax
int $0x1b
lret
/*
* Print out the error message, wait for a keypress, and then reboot
* the machine.
*/
error: push %cs
pop %ds
mov $msg_eread,%si
call putstr
xor %ax,%ax /* Get keypress */
int $0x18
xor %ax,%ax /* CPU reset */
outb %al,$0xf0
halt: hlt
jmp halt /* Spin */
/*
* Display a null-terminated string.
*/
putstr.0: push %cs
callw putc
putstr: lodsb
test %al,%al
jne putstr.0
ret
/*
* Display a single char.
*/
putc: pusha
xor %dx,%dx
mov %dx,%ds
mov MEM_REL+cursor-start,%di
mov $0xa000,%bx
mov %bx,%es
mov $(80*2),%cx
cmp $0x08,%al
je putc.bs
cmp $0x0d,%al
je putc.cr
cmp $0x0a,%al
je putc.lf
cmp $0x5c,%al /* \ */
jne 1f
mov $0xfc,%al
1: movb $0xe1,%es:0x2000(%di)
stosw
jmp putc.scr
putc.bs: test %di,%di
jz putc.move
dec %di
dec %di
movb $0xe1,%es:0x2000(%di)
movw $0x20,%es:(%di)
jmp putc.move
putc.cr: mov %di,%ax
div %cx
sub %dx,%di
jmp putc.move
putc.lf: add %cx,%di
putc.scr: cmp $(80*2*25),%di /* Scroll screen */
jb putc.move
push %ds
mov %bx,%ds
mov $(80*2),%si
xor %di,%di
mov $(80*24/2),%cx
rep
movsl
xor %ax,%ax
mov $0x20,%al
mov $80,%cl
rep
stosw
pop %ds
mov $(80*24*2),%di
putc.move: mov %di,MEM_REL+cursor-start /* Move cursor */
mov $0x13,%ah
mov %di,%dx
int $0x18
popa
lret
cursor: .word 0
#ifdef SET_MACHINE_TYPE
/*
* Set machine type to PC98_SYSTEM_PARAMETER.
*/
set_machine_type:
xor %edx,%edx
mov %dx,%ds
// mov $MEM_SYS,%ax
// mov %ax,%es
/* Wait V-SYNC */
vsync.1: inb $0x60,%al
test $0x20,%al
jnz vsync.1
vsync.2: inb $0x60,%al
test $0x20,%al
jz vsync.2
/* ANK 'A' font */
xor %al,%al
outb %al,$0xa1
mov $0x41,%al
outb %al,$0xa3
/* Get 'A' font from CG window */
push %ds
mov $0xa400,%ax
mov %ax,%ds
xor %eax,%eax
xor %bx,%bx
mov $4,%cx
font.1: add (%bx),%eax
add $4,%bx
loop font.1
pop %ds
cmp $0x6efc58fc,%eax
jnz m_epson
m_pc98: or $M_NEC_PC98,%edx
mov $0x0458,%bx
mov (%bx),%al
test $0x80,%al
jz m_not_h98
or $M_H98,%edx
jmp 1f
m_epson: or $M_EPSON_PC98,%edx
m_not_h98: or $M_NOT_H98,%edx
1: inb $0x42,%al
test $0x20,%al
jz 1f
or $M_8M,%edx
1: mov $0x0400,%bx
mov (%bx),%al
test $0x80,%al
jz 1f
or $M_NOTE,%edx
1: mov $PC98_MACHINE_TYPE,%bx
mov %edx,%es:(%bx)
ret
#endif
/* Messages */
msg_eread: .asciz "Error\r\n"
.org PRT_OFF,0x90
/* Partition table */
.fill 0x30,0x1,0x0
.byte 0x80, 0x00, 0x01, 0x00
.byte 0xa5, 0xff, 0xff, 0xff
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x50, 0xc3, 0x00, 0x00
.word 0xaa55 # Magic number

803
sys/boot/pc98/boot2/boot2.c Normal file
View File

@ -0,0 +1,803 @@
/*-
* Copyright (c) 2008-2009 TAKAHASHI Yoshihiro
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/diskpc98.h>
#include <sys/dirent.h>
#include <sys/reboot.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
#include <machine/elf.h>
#include <stdarg.h>
#include <a.out.h>
#include <btxv86.h>
#include "boot2.h"
#include "lib.h"
#include "paths.h"
#include "rbx.h"
/* Define to 0 to omit serial support */
#ifndef SERIAL
#define SERIAL 0
#endif
#define IO_KEYBOARD 1
#define IO_SERIAL 2
#if SERIAL
#define DO_KBD (ioctrl & IO_KEYBOARD)
#define DO_SIO (ioctrl & IO_SERIAL)
#else
#define DO_KBD (1)
#define DO_SIO (0)
#endif
#define SECOND 1 /* Circa that many ticks in a second. */
#define ARGS 0x900
#define NOPT 14
#define NDEV 3
#define DRV_DISK 0xf0
#define DRV_UNIT 0x0f
#define TYPE_AD 0
#define TYPE_DA 1
#define TYPE_FD 2
extern uint32_t _end;
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
static const unsigned char flags[NOPT] = {
RBX_DUAL,
RBX_SERIAL,
RBX_ASKNAME,
RBX_CDROM,
RBX_CONFIG,
RBX_KDB,
RBX_GDB,
RBX_MUTE,
RBX_NOINTR,
RBX_PAUSE,
RBX_QUIET,
RBX_DFLTROOT,
RBX_SINGLE,
RBX_VERBOSE
};
static const char *const dev_nm[NDEV] = {"ad", "da", "fd"};
static const unsigned char dev_maj[NDEV] = {30, 4, 2};
static const unsigned char dev_daua[NDEV] = {0x80, 0xa0, 0x90};
static struct dsk {
unsigned daua;
unsigned type;
unsigned disk;
unsigned unit;
unsigned head;
unsigned sec;
uint8_t slice;
uint8_t part;
unsigned start;
} dsk;
static char cmd[512], cmddup[512], knamebuf[1024];
static const char *kname;
uint32_t opts;
static struct bootinfo bootinfo;
#if SERIAL
static int comspeed = SIOSPD;
static uint8_t ioctrl = IO_KEYBOARD;
#endif
int main(void);
void exit(int);
static void load(void);
static int parse(void);
static int dskread(void *, unsigned, unsigned);
static void printf(const char *,...);
static void putchar(int);
static int drvread(void *, unsigned);
static int keyhit(unsigned);
static int xputc(int);
static int xgetc(int);
static inline int getc(int);
static void memcpy(void *, const void *, int);
static void
memcpy(void *dst, const void *src, int len)
{
const char *s = src;
char *d = dst;
while (len--)
*d++ = *s++;
}
static inline int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++);
return (unsigned char)*s1 - (unsigned char)*s2;
}
#define UFS_SMALL_CGBASE
#include "ufsread.c"
static inline int
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static inline void
getstr(void)
{
char *s;
int c;
s = cmd;
for (;;) {
switch (c = xgetc(0)) {
case 0:
break;
case '\177':
case '\b':
if (s > cmd) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if (s - cmd < sizeof(cmd) - 1)
*s++ = c;
putchar(c);
}
}
}
static inline void
putc(int c)
{
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = PUTCORG; /* call to putc in boot1 */
v86.eax = c;
v86int();
v86.ctl = V86_FLAGS;
}
static inline int
is_scsi_hd(void)
{
if ((*(u_char *)PTOV(0x482) >> dsk.unit) & 0x01)
return 1;
return 0;
}
static inline void
fix_sector_size(void)
{
u_char *p;
p = (u_char *)PTOV(0x460 + dsk.unit * 4); /* SCSI equipment parameter */
if ((p[0] & 0x1f) == 7) { /* SCSI MO */
if (!(p[3] & 0x30)) { /* 256B / sector */
p[3] |= 0x10; /* forced set 512B / sector */
p[3 + 0xa1000] |= 0x10;
}
}
}
static inline uint32_t
get_diskinfo(void)
{
if (dsk.disk == 0x30) { /* 1440KB FD */
/* 80 cylinders, 2 heads, 18 sectors */
return (80 << 16) | (2 << 8) | 18;
} else if (dsk.disk == 0x90) { /* 1200KB FD */
/* 80 cylinders, 2 heads, 15 sectors */
return (80 << 16) | (2 << 8) | 15;
} else if (dsk.disk == 0x80 || is_scsi_hd()) { /* IDE or SCSI HDD */
v86.addr = 0x1b;
v86.eax = 0x8400 | dsk.daua;
v86int();
return (v86.ecx << 16) | v86.edx;
}
/* SCSI MO or CD */
fix_sector_size(); /* SCSI MO */
/* other SCSI devices */
return (65535 << 16) | (8 << 8) | 32;
}
static void
set_dsk(void)
{
uint32_t di;
di = get_diskinfo();
dsk.head = (di >> 8) & 0xff;
dsk.sec = di & 0xff;
dsk.start = 0;
}
#ifdef GET_BIOSGEOM
static uint32_t
bd_getbigeom(int bunit)
{
int hds = 0;
int unit = 0x80; /* IDE HDD */
u_int addr = 0x55d;
while (unit < 0xa7) {
if (*(u_char *)PTOV(addr) & (1 << (unit & 0x0f)))
if (hds++ == bunit)
break;
if (unit >= 0xA0) {
int media = ((unsigned *)PTOV(0x460))[unit & 0x0F] & 0x1F;
if (media == 7 && hds++ == bunit) /* SCSI MO */
return(0xFFFE0820); /* C:65535 H:8 S:32 */
}
if (++unit == 0x84) {
unit = 0xA0; /* SCSI HDD */
addr = 0x482;
}
}
if (unit == 0xa7)
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
if (V86_CY(v86.efl))
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
#endif
static int
check_slice(void)
{
struct pc98_partition *dp;
char *sec;
unsigned i, cyl;
sec = dmadat->secbuf;
cyl = *(uint16_t *)PTOV(ARGS);
set_dsk();
if (dsk.type == TYPE_FD)
return (WHOLE_DISK_SLICE);
if (drvread(sec, PC98_BBSECTOR))
return (WHOLE_DISK_SLICE); /* Read error */
dp = (void *)(sec + PC98_PARTOFF);
for (i = 0; i < PC98_NPARTS; i++) {
if (dp[i].dp_mid == DOSMID_386BSD) {
if (dp[i].dp_scyl <= cyl && cyl <= dp[i].dp_ecyl)
return (BASE_SLICE + i);
}
}
return (WHOLE_DISK_SLICE);
}
int
main(void)
{
#ifdef GET_BIOSGEOM
int i;
#endif
uint8_t autoboot;
ufs_ino_t ino;
size_t nbyte;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
dsk.daua = *(uint8_t *)PTOV(0x584);
dsk.disk = dsk.daua & DRV_DISK;
dsk.unit = dsk.daua & DRV_UNIT;
if (dsk.disk == 0x80)
dsk.type = TYPE_AD;
else if (dsk.disk == 0xa0)
dsk.type = TYPE_DA;
else /* if (dsk.disk == 0x30 || dsk.disk == 0x90) */
dsk.type = TYPE_FD;
dsk.slice = check_slice();
#ifdef GET_BIOSGEOM
for (i = 0; i < N_BIOS_GEOM; i++)
bootinfo.bi_bios_geom[i] = bd_getbigeom(i);
#endif
bootinfo.bi_version = BOOTINFO_VERSION;
bootinfo.bi_size = sizeof(bootinfo);
/* Process configuration file */
autoboot = 1;
if ((ino = lookup(PATH_CONFIG)) ||
(ino = lookup(PATH_DOTCONFIG))) {
nbyte = fsread(ino, cmd, sizeof(cmd) - 1);
cmd[nbyte] = '\0';
}
if (*cmd) {
memcpy(cmddup, cmd, sizeof(cmd));
if (parse())
autoboot = 0;
if (!OPT_CHECK(RBX_QUIET))
printf("%s: %s", PATH_CONFIG, cmddup);
/* Do not process this command twice */
*cmd = 0;
}
/*
* Try to exec stage 3 boot loader. If interrupted by a keypress,
* or in case of failure, try to load a kernel directly instead.
*/
if (!kname) {
kname = PATH_LOADER;
if (autoboot && !keyhit(3*SECOND)) {
load();
kname = PATH_KERNEL;
}
}
/* Present the user with the boot2 prompt. */
for (;;) {
if (!autoboot || !OPT_CHECK(RBX_QUIET))
printf("\nFreeBSD/pc98 boot\n"
"Default: %u:%s(%u,%c)%s\n"
"boot: ",
dsk.unit, dev_nm[dsk.type], dsk.unit,
'a' + dsk.part, kname);
if (DO_SIO)
sio_flush();
if (!autoboot || keyhit(3*SECOND))
getstr();
else if (!autoboot || !OPT_CHECK(RBX_QUIET))
putchar('\n');
autoboot = 0;
if (parse())
putchar('\a');
else
load();
}
}
/* XXX - Needed for btxld to link the boot2 binary; do not remove. */
void
exit(int x)
{
}
static void
load(void)
{
union {
struct exec ex;
Elf32_Ehdr eh;
} hdr;
static Elf32_Phdr ep[2];
static Elf32_Shdr es[2];
caddr_t p;
ufs_ino_t ino;
uint32_t addr;
int k;
uint8_t i, j;
if (!(ino = lookup(kname))) {
if (!ls)
printf("No %s\n", kname);
return;
}
if (xfsread(ino, &hdr, sizeof(hdr)))
return;
if (N_GETMAGIC(hdr.ex) == ZMAGIC) {
addr = hdr.ex.a_entry & 0xffffff;
p = PTOV(addr);
fs_off = PAGE_SIZE;
if (xfsread(ino, p, hdr.ex.a_text))
return;
p += roundup2(hdr.ex.a_text, PAGE_SIZE);
if (xfsread(ino, p, hdr.ex.a_data))
return;
} else if (IS_ELF(hdr.eh)) {
fs_off = hdr.eh.e_phoff;
for (j = k = 0; k < hdr.eh.e_phnum && j < 2; k++) {
if (xfsread(ino, ep + j, sizeof(ep[0])))
return;
if (ep[j].p_type == PT_LOAD)
j++;
}
for (i = 0; i < 2; i++) {
p = PTOV(ep[i].p_paddr & 0xffffff);
fs_off = ep[i].p_offset;
if (xfsread(ino, p, ep[i].p_filesz))
return;
}
p += roundup2(ep[1].p_memsz, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
fs_off = hdr.eh.e_shoff + sizeof(es[0]) *
(hdr.eh.e_shstrndx + 1);
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
*(Elf32_Word *)p = es[i].sh_size;
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
return;
p += es[i].sh_size;
}
}
addr = hdr.eh.e_entry & 0xffffff;
bootinfo.bi_esymtab = VTOP(p);
} else {
printf("Invalid %s\n", "format");
return;
}
bootinfo.bi_kernelname = VTOP(kname);
bootinfo.bi_bios_dev = dsk.daua;
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
static int
parse()
{
char *arg = cmd;
char *ep, *p, *q;
const char *cp;
unsigned int drv;
int c, i, j;
size_t k;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
continue;
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
ep = p;
if (*p)
*p++ = 0;
if (c == '-') {
while ((c = *arg++)) {
if (c == 'P') {
if (*(uint8_t *)PTOV(0x481) & 0x48) {
cp = "yes";
} else {
opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL);
cp = "no";
}
printf("Keyboard: %s\n", cp);
continue;
#if SERIAL
} else if (c == 'S') {
j = 0;
while ((unsigned int)(i = *arg++ - '0') <= 9)
j = j * 10 + i;
if (j > 0 && i == -'0') {
comspeed = j;
break;
}
/* Fall through to error below ('S' not in optstr[]). */
#endif
}
for (i = 0; c != optstr[i]; i++)
if (i == NOPT - 1)
return -1;
opts ^= OPT_SET(flags[i]);
}
#if SERIAL
ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
if (DO_SIO) {
if (sio_init(115200 / comspeed) != 0)
ioctrl &= ~IO_SERIAL;
}
#endif
} else {
for (q = arg--; *q && *q != '('; q++);
if (*q) {
drv = -1;
if (arg[1] == ':') {
drv = *arg - '0';
if (drv > 9)
return (-1);
arg += 2;
}
if (q - arg != 2)
return -1;
for (i = 0; arg[0] != dev_nm[i][0] ||
arg[1] != dev_nm[i][1]; i++)
if (i == NDEV - 1)
return -1;
dsk.type = i;
arg += 3;
dsk.unit = *arg - '0';
if (arg[1] != ',' || dsk.unit > 9)
return -1;
arg += 2;
dsk.slice = WHOLE_DISK_SLICE;
if (arg[1] == ',') {
dsk.slice = *arg - '0' + 1;
if (dsk.slice > PC98_NPARTS + 1)
return -1;
arg += 2;
}
if (arg[1] != ')')
return -1;
dsk.part = *arg - 'a';
if (dsk.part > 7)
return (-1);
arg += 2;
if (drv == -1)
drv = dsk.unit;
dsk.disk = dev_daua[dsk.type];
dsk.daua = dsk.disk | dsk.unit;
dsk_meta = 0;
}
k = ep - arg;
if (k > 0) {
if (k >= sizeof(knamebuf))
return -1;
memcpy(knamebuf, arg, k + 1);
kname = knamebuf;
}
}
arg = p;
}
return 0;
}
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct pc98_partition *dp;
struct disklabel *d;
char *sec;
unsigned i;
uint8_t sl;
u_char *p;
const char *reason;
if (!dsk_meta) {
sec = dmadat->secbuf;
set_dsk();
if (dsk.type == TYPE_FD)
goto unsliced;
if (drvread(sec, PC98_BBSECTOR))
return -1;
dp = (void *)(sec + PC98_PARTOFF);
sl = dsk.slice;
if (sl < BASE_SLICE) {
for (i = 0; i < PC98_NPARTS; i++)
if (dp[i].dp_mid == DOSMID_386BSD) {
sl = BASE_SLICE + i;
break;
}
dsk.slice = sl;
}
if (sl != WHOLE_DISK_SLICE) {
dp += sl - BASE_SLICE;
if (dp->dp_mid != DOSMID_386BSD) {
reason = "slice";
goto error;
}
dsk.start = dp->dp_scyl * dsk.head * dsk.sec +
dp->dp_shd * dsk.sec + dp->dp_ssect;
}
if (drvread(sec, dsk.start + LABELSECTOR))
return -1;
d = (void *)(sec + LABELOFFSET);
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
if (dsk.part != RAW_PART) {
reason = "label";
goto error;
}
} else {
if (dsk.part >= d->d_npartitions ||
!d->d_partitions[dsk.part].p_size) {
reason = "partition";
goto error;
}
dsk.start += d->d_partitions[dsk.part].p_offset;
dsk.start -= d->d_partitions[RAW_PART].p_offset;
}
unsliced: ;
}
for (p = buf; nblk; p += 512, lba++, nblk--) {
if ((i = drvread(p, dsk.start + lba)))
return i;
}
return 0;
error:
printf("Invalid %s\n", reason);
return -1;
}
static void
printf(const char *fmt,...)
{
va_list ap;
static char buf[10];
char *s;
unsigned u;
int c;
va_start(ap, fmt);
while ((c = *fmt++)) {
if (c == '%') {
c = *fmt++;
switch (c) {
case 'c':
putchar(va_arg(ap, int));
continue;
case 's':
for (s = va_arg(ap, char *); *s; s++)
putchar(*s);
continue;
case 'u':
u = va_arg(ap, unsigned);
s = buf;
do
*s++ = '0' + u % 10U;
while (u /= 10U);
while (--s >= buf)
putchar(*s);
continue;
}
}
putchar(c);
}
va_end(ap);
return;
}
static void
putchar(int c)
{
if (c == '\n')
xputc('\r');
xputc(c);
}
static int
drvread(void *buf, unsigned lba)
{
static unsigned c = 0x2d5c7c2f;
unsigned bpc, x, cyl, head, sec;
bpc = dsk.sec * dsk.head;
cyl = lba / bpc;
x = lba % bpc;
head = x / dsk.sec;
sec = x % dsk.sec;
if (!OPT_CHECK(RBX_QUIET)) {
xputc(c = c << 8 | c >> 24);
xputc('\b');
}
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = READORG; /* call to read in boot1 */
v86.ecx = cyl;
v86.edx = (head << 8) | sec;
v86.edi = lba;
v86.ebx = 512;
v86.es = VTOPSEG(buf);
v86.ebp = VTOPOFF(buf);
v86int();
v86.ctl = V86_FLAGS;
if (V86_CY(v86.efl)) {
printf("error %u c/h/s %u/%u/%u lba %u\n", v86.eax >> 8 & 0xff,
cyl, head, sec, lba);
return -1;
}
return 0;
}
static inline void
delay(void)
{
int i;
i = 800;
do {
outb(0x5f, 0); /* about 600ns */
} while (--i >= 0);
}
static int
keyhit(unsigned sec)
{
unsigned i;
if (OPT_CHECK(RBX_NOINTR))
return 0;
for (i = 0; i < sec * 1000; i++) {
if (xgetc(1))
return 1;
delay();
}
return 0;
}
static int
xputc(int c)
{
if (DO_KBD)
putc(c);
if (DO_SIO)
sio_putc(c);
return c;
}
static int
getc(int fn)
{
v86.addr = 0x18;
v86.eax = fn << 8;
v86int();
if (fn)
return (v86.ebx >> 8) & 0x01;
else
return v86.eax & 0xff;
}
static int
xgetc(int fn)
{
if (OPT_CHECK(RBX_NOINTR))
return 0;
for (;;) {
if (DO_KBD && getc(1))
return fn ? 1 : getc(0);
if (DO_SIO && sio_ischar())
return fn ? 1 : sio_getc();
if (fn)
return 0;
}
}

View File

@ -0,0 +1,5 @@
# $FreeBSD$
SUBDIR= btx btxldr lib
.include <bsd.subdir.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.include "../Makefile.inc"

View File

@ -0,0 +1,33 @@
# $FreeBSD$
PROG= btx
INTERNALPROG=
MAN=
SRCS= btx.S
.if defined(BOOT_BTX_NOHANG)
BOOT_BTX_FLAGS=0x1
.else
BOOT_BTX_FLAGS=0x0
.endif
CFLAGS+=-DBTX_FLAGS=${BOOT_BTX_FLAGS}
CFLAGS+=-I${.CURDIR}/../../../i386/common
.if defined(BTX_SERIAL)
BOOT_COMCONSOLE_PORT?= 0x238
BOOT_COMCONSOLE_SPEED?= 9600
B2SIOFMT?= 0x3
CFLAGS+=-DBTX_SERIAL -DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} -DSIOSPD=${BOOT_COMCONSOLE_SPEED}
.endif
ORG= 0x9000
LDFLAGS=${LDFLAGS_BIN}
.include <bsd.prog.mk>
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btx.S= ${CLANG_NO_IAS}

1104
sys/boot/pc98/btx/btx/btx.S Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
# $FreeBSD$
PROG= btxldr
INTERNALPROG=
MAN=
SRCS= btxldr.S
CFLAGS+=-DLOADER_ADDRESS=${LOADER_ADDRESS}
CFLAGS+=-I${.CURDIR}/../../../i386/common
.if defined(BTXLDR_VERBOSE)
CFLAGS+=-DBTXLDR_VERBOSE
.endif
ORG=${LOADER_ADDRESS}
LDFLAGS=${LDFLAGS_BIN}
.include <bsd.prog.mk>
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btxldr.S= ${CLANG_NO_IAS}

View File

@ -0,0 +1,430 @@
/*
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*
* $FreeBSD$
*/
#include <bootargs.h>
/*
* Prototype BTX loader program, written in a couple of hours. The
* real thing should probably be more flexible, and in C.
*/
/*
* Memory locations.
*/
.set MEM_STUB,0x600 # Real mode stub
.set MEM_ESP,0x1000 # New stack pointer
.set MEM_TBL,0x5000 # BTX page tables
.set MEM_ENTRY,0x9010 # BTX entry point
.set MEM_DATA,start+0x1000 # Data segment
/*
* Segment selectors.
*/
.set SEL_SCODE,0x8 # 4GB code
.set SEL_SDATA,0x10 # 4GB data
.set SEL_RCODE,0x18 # 64K code
.set SEL_RDATA,0x20 # 64K data
/*
* Paging constants.
*/
.set PAG_SIZ,0x1000 # Page size
.set PAG_ENT,0x4 # Page entry size
/*
* Screen constants.
*/
.set SCR_MAT,0xe1 # Mode/attribute
.set SCR_COL,0x50 # Columns per row
.set SCR_ROW,0x19 # Rows per screen
/*
* BIOS Data Area locations.
*/
.set BDA_MEM,0xa1501 # Free memory
.set BDA_POS,0xa153e # Cursor position
/*
* Required by aout gas inadequacy.
*/
.set SIZ_STUB,0x1a # Size of stub
/*
* We expect to be loaded by boot2 at the origin defined in ./Makefile.
*/
.globl start
/*
* BTX program loader for ELF clients.
*/
start: cld # String ops inc
cli
gdcwait.1: inb $0x60,%al
testb $0x04,%al
jz gdcwait.1
movb $0xe0,%al
outb %al,$0x62
nop
gdcwait.2: inb $0x60,%al
testb $0x01,%al
jz gdcwait.2
inb $0x62,%al
movb %al,%dl
inb $0x62,%al
movb %al,%dh
inb $0x62,%al
inb $0x62,%al
inb $0x62,%al
shlw $1,%dx
movl $BDA_POS,%ebx
movw %dx,(%ebx)
movl $m_logo,%esi # Identify
call putstr # ourselves
movzwl BDA_MEM,%eax # Get base memory
andl $0x7,%eax
incl %eax
shll $0x11,%eax # in bytes
movl %eax,%ebp # Base of user stack
#ifdef BTXLDR_VERBOSE
movl $m_mem,%esi # Display
call hexout # amount of
call putstr # base memory
#endif
lgdt gdtdesc # Load new GDT
/*
* Relocate caller's arguments.
*/
#ifdef BTXLDR_VERBOSE
movl $m_esp,%esi # Display
movl %esp,%eax # caller
call hexout # stack
call putstr # pointer
movl $m_args,%esi # Format string
leal 0x4(%esp),%ebx # First argument
movl $0x6,%ecx # Count
start.1: movl (%ebx),%eax # Get argument and
addl $0x4,%ebx # bump pointer
call hexout # Display it
loop start.1 # Till done
call putstr # End message
#endif
movl BA_BOOTINFO+4(%esp),%esi # Source: bootinfo
cmpl $0x0, %esi # If the bootinfo pointer
je start_null_bi # is null, don't copy it
movl BI_SIZE(%esi),%ecx # Allocate space
subl %ecx,%ebp # for bootinfo
movl %ebp,%edi # Destination
rep # Copy
movsb # it
movl %ebp,BA_BOOTINFO+4(%esp) # Update pointer
movl %edi,%ebp # Restore base pointer
#ifdef BTXLDR_VERBOSE
movl $m_rel_bi,%esi # Display
movl %ebp,%eax # bootinfo
call hexout # relocation
call putstr # message
#endif
start_null_bi: movl $BOOTARGS_SIZE,%ecx # Fixed size of arguments
testl $KARGS_FLAGS_EXTARG, BA_BOOTFLAGS+4(%esp) # Check for extra data
jz start_fixed # Skip if the flag is not set
addl BOOTARGS_SIZE+4(%esp),%ecx # Add size of variable args
start_fixed: subl $ARGOFF,%ebp # Place args at fixed offset
leal 0x4(%esp),%esi # Source
movl %ebp,%edi # Destination
rep # Copy
movsb # them
#ifdef BTXLDR_VERBOSE
movl $m_rel_args,%esi # Display
movl %ebp,%eax # argument
call hexout # relocation
call putstr # message
#endif
/*
* Set up BTX kernel.
*/
movl $MEM_ESP,%esp # Set up new stack
movl $MEM_DATA,%ebx # Data segment
movl $m_vers,%esi # Display BTX
call putstr # version message
movb 0x5(%ebx),%al # Get major version
addb $'0',%al # Display
call putchr # it
movb $'.',%al # And a
call putchr # dot
movb 0x6(%ebx),%al # Get minor
xorb %ah,%ah # version
movb $0xa,%dl # Divide
divb %dl,%al # by 10
addb $'0',%al # Display
call putchr # tens
movb %ah,%al # Get units
addb $'0',%al # Display
call putchr # units
call putstr # End message
movl %ebx,%esi # BTX image
movzwl 0x8(%ebx),%edi # Compute
orl $PAG_SIZ/PAG_ENT-1,%edi # the
incl %edi # BTX
shll $0x2,%edi # load
addl $MEM_TBL,%edi # address
pushl %edi # Save load address
movzwl 0xa(%ebx),%ecx # Image size
#ifdef BTXLDR_VERBOSE
pushl %ecx # Save image size
#endif
rep # Relocate
movsb # BTX
movl %esi,%ebx # Keep place
#ifdef BTXLDR_VERBOSE
movl $m_rel_btx,%esi # Restore
popl %eax # parameters
call hexout # and
#endif
popl %ebp # display
#ifdef BTXLDR_VERBOSE
movl %ebp,%eax # the
call hexout # relocation
call putstr # message
#endif
addl $PAG_SIZ,%ebp # Display
#ifdef BTXLDR_VERBOSE
movl $m_base,%esi # the
movl %ebp,%eax # user
call hexout # base
call putstr # address
#endif
/*
* Set up ELF-format client program.
*/
cmpl $0x464c457f,(%ebx) # ELF magic number?
je start.3 # Yes
movl $e_fmt,%esi # Display error
call putstr # message
start.2: jmp start.2 # Hang
start.3:
#ifdef BTXLDR_VERBOSE
movl $m_elf,%esi # Display ELF
call putstr # message
movl $m_segs,%esi # Format string
#endif
movl $0x2,%edi # Segment count
movl 0x1c(%ebx),%edx # Get e_phoff
addl %ebx,%edx # To pointer
movzwl 0x2c(%ebx),%ecx # Get e_phnum
start.4: cmpl $0x1,(%edx) # Is p_type PT_LOAD?
jne start.6 # No
#ifdef BTXLDR_VERBOSE
movl 0x4(%edx),%eax # Display
call hexout # p_offset
movl 0x8(%edx),%eax # Display
call hexout # p_vaddr
movl 0x10(%edx),%eax # Display
call hexout # p_filesz
movl 0x14(%edx),%eax # Display
call hexout # p_memsz
call putstr # End message
#endif
pushl %esi # Save
pushl %edi # working
pushl %ecx # registers
movl 0x4(%edx),%esi # Get p_offset
addl %ebx,%esi # as pointer
movl 0x8(%edx),%edi # Get p_vaddr
addl %ebp,%edi # as pointer
movl 0x10(%edx),%ecx # Get p_filesz
rep # Set up
movsb # segment
movl 0x14(%edx),%ecx # Any bytes
subl 0x10(%edx),%ecx # to zero?
jz start.5 # No
xorb %al,%al # Then
rep # zero
stosb # them
start.5: popl %ecx # Restore
popl %edi # working
popl %esi # registers
decl %edi # Segments to do
je start.7 # If none
start.6: addl $0x20,%edx # To next entry
loop start.4 # Till done
start.7:
#ifdef BTXLDR_VERBOSE
movl $m_done,%esi # Display done
call putstr # message
#endif
movl $start.8,%esi # Real mode stub
movl $MEM_STUB,%edi # Destination
movl $start.9-start.8,%ecx # Size
rep # Relocate
movsb # it
ljmp $SEL_RCODE,$MEM_STUB # To 16-bit code
.code16
start.8: xorw %ax,%ax # Data
movb $SEL_RDATA,%al # selector
movw %ax,%ss # Reload SS
movw %ax,%ds # Reset
movw %ax,%es # other
movw %ax,%fs # segment
movw %ax,%gs # limits
movl %cr0,%eax # Switch to
decw %ax # real
movl %eax,%cr0 # mode
ljmp $0,$MEM_ENTRY # Jump to BTX entry point
start.9:
.code32
/*
* Output message [ESI] followed by EAX in hex.
*/
hexout: pushl %eax # Save
call putstr # Display message
popl %eax # Restore
pushl %esi # Save
pushl %edi # caller's
movl $buf,%edi # Buffer
pushl %edi # Save
call hex32 # To hex
xorb %al,%al # Terminate
stosb # string
popl %esi # Restore
hexout.1: lodsb # Get a char
cmpb $'0',%al # Leading zero?
je hexout.1 # Yes
testb %al,%al # End of string?
jne hexout.2 # No
decl %esi # Undo
hexout.2: decl %esi # Adjust for inc
call putstr # Display hex
popl %edi # Restore
popl %esi # caller's
ret # To caller
/*
* Output zero-terminated string [ESI] to the console.
*/
putstr.0: call putchr # Output char
putstr: lodsb # Load char
testb %al,%al # End of string?
jne putstr.0 # No
ret # To caller
/*
* Output character AL to the console.
*/
putchr: pusha # Save
xorl %ecx,%ecx # Zero for loops
movb $SCR_MAT,%ah # Mode/attribute
movl $BDA_POS,%ebx # BDA pointer
movw (%ebx),%dx # Cursor position
movl $0xa0000,%edi # Regen buffer (color)
putchr.1: cmpb $0xa,%al # New line?
je putchr.2 # Yes
movw %dx,%cx
movb %al,(%edi,%ecx,1) # Write char
addl $0x2000,%ecx
movb %ah,(%edi,%ecx,1) # Write attr
addw $0x2,%dx
jmp putchr.3
putchr.2: movw %dx,%ax
movb $SCR_COL*2,%dl
div %dl
incb %al
mul %dl
movw %ax,%dx
putchr.3: cmpw $SCR_COL*SCR_ROW*2,%dx
jb putchr.4 # No
leal 2*SCR_COL(%edi),%esi # New top line
movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
rep # Scroll
movsl # screen
movb $' ',%al # Space
xorb %ah,%ah
movb $SCR_COL,%cl # Columns to clear
rep # Clear
stosw # line
movw $(SCR_ROW-1)*SCR_COL*2,%dx
putchr.4: movw %dx,(%ebx) # Update position
shrw $1,%dx
gdcwait.3: inb $0x60,%al
testb $0x04,%al
jz gdcwait.3
movb $0x49,%al
outb %al,$0x62
movb %dl,%al
outb %al,$0x60
movb %dh,%al
outb %al,$0x60
popa # Restore
ret # To caller
/*
* Convert EAX, AX, or AL to hex, saving the result to [EDI].
*/
hex32: pushl %eax # Save
shrl $0x10,%eax # Do upper
call hex16 # 16
popl %eax # Restore
hex16: call hex16.1 # Do upper 8
hex16.1: xchgb %ah,%al # Save/restore
hex8: pushl %eax # Save
shrb $0x4,%al # Do upper
call hex8.1 # 4
popl %eax # Restore
hex8.1: andb $0xf,%al # Get lower 4
cmpb $0xa,%al # Convert
sbbb $0x69,%al # to hex
das # digit
orb $0x20,%al # To lower case
stosb # Save char
ret # (Recursive)
.data
.p2align 4
/*
* Global descriptor table.
*/
gdt: .word 0x0,0x0,0x0,0x0 # Null entry
.word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE
.word 0xffff,0x0,0x9200,0xcf # SEL_SDATA
.word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE
.word 0xffff,0x0,0x9200,0x0 # SEL_RDATA
gdt.1:
gdtdesc: .word gdt.1-gdt-1 # Limit
.long gdt # Base
/*
* Messages.
*/
m_logo: .asciz " \nBTX loader 1.00 "
m_vers: .asciz "BTX version is \0\n"
e_fmt: .asciz "Error: Client format not supported\n"
#ifdef BTXLDR_VERBOSE
m_mem: .asciz "Starting in protected mode (base mem=\0)\n"
m_esp: .asciz "Arguments passed (esp=\0):\n"
m_args: .asciz"<howto="
.asciz" bootdev="
.asciz" junk="
.asciz" "
.asciz" "
.asciz" bootinfo=\0>\n"
m_rel_bi: .asciz "Relocated bootinfo (size=48) to \0\n"
m_rel_args: .asciz "Relocated arguments (size=18) to \0\n"
m_rel_btx: .asciz "Relocated kernel (size=\0) to \0\n"
m_base: .asciz "Client base address is \0\n"
m_elf: .asciz "Client format is ELF\n"
m_segs: .asciz "text segment: offset="
.asciz " vaddr="
.asciz " filesz="
.asciz " memsz=\0\n"
.asciz "data segment: offset="
.asciz " vaddr="
.asciz " filesz="
.asciz " memsz=\0\n"
m_done: .asciz "Loading complete\n"
#endif
/*
* Uninitialized data area.
*/
buf: # Scratch buffer

View File

@ -0,0 +1,10 @@
# $FreeBSD$
PROG= crt0.o
INTERNALPROG=
MAN=
SRCS= btxcsu.S btxsys.s btxv86.s
CFLAGS+=-I${.CURDIR}/../../../i386/common
LDFLAGS=-Wl,-r
.include <bsd.prog.mk>

View File

@ -0,0 +1,49 @@
#
# Copyright (c) 1998 Robert Nordier
# All rights reserved.
#
# Redistribution and use in source and binary forms are freely
# permitted provided that the above copyright notice and this
# paragraph and the following disclaimer are duplicated in all
# such forms.
#
# This software is provided "AS IS" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantability and fitness for a particular
# purpose.
#
# $FreeBSD$
#include <bootargs.h>
#
# BTX C startup code (ELF).
#
#
# Globals.
#
.global _start
#
# Client entry point.
#
_start: cld
pushl %eax
movl $_edata,%edi
movl $_end,%ecx
subl %edi, %ecx
xorb %al, %al
rep
stosb
popl __base
movl %esp,%eax # Set
addl $ARGADJ,%eax # argument
movl %eax,__args # pointer
call main # Invoke client main()
call exit # Invoke client exit()
#
# Data.
#
.comm __base,4 # Client base address
.comm __args,4 # Client arguments

View File

@ -0,0 +1,40 @@
#
# Copyright (c) 1998 Robert Nordier
# All rights reserved.
#
# Redistribution and use in source and binary forms are freely
# permitted provided that the above copyright notice and this
# paragraph and the following disclaimer are duplicated in all
# such forms.
#
# This software is provided "AS IS" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantability and fitness for a particular
# purpose.
#
# $FreeBSD$
#
# BTX system calls.
#
#
# Globals.
#
.global __exit
.global __exec
#
# Constants.
#
.set INT_SYS,0x30 # Interrupt number
#
# System call: exit
#
__exit: xorl %eax,%eax # BTX system
int $INT_SYS # call 0x0
#
# System call: exec
#
__exec: movl $0x1,%eax # BTX system
int $INT_SYS # call 0x1

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
/*
* $FreeBSD$
*/
#ifndef _BTXV86_H_
#define _BTXV86_H_
#include <sys/types.h>
#include <machine/psl.h>
#define V86_ADDR 0x10000 /* Segment:offset address */
#define V86_CALLF 0x20000 /* Emulate far call */
#define V86_FLAGS 0x40000 /* Return flags */
struct __v86 {
uint32_t ctl; /* Control flags */
uint32_t addr; /* Interrupt number or address */
uint32_t es; /* V86 ES register */
uint32_t ds; /* V86 DS register */
uint32_t fs; /* V86 FS register */
uint32_t gs; /* V86 GS register */
uint32_t eax; /* V86 EAX register */
uint32_t ecx; /* V86 ECX register */
uint32_t edx; /* V86 EDX register */
uint32_t ebx; /* V86 EBX register */
uint32_t efl; /* V86 eflags register */
uint32_t ebp; /* V86 EBP register */
uint32_t esi; /* V86 ESI register */
uint32_t edi; /* V86 EDI register */
};
extern struct __v86 __v86; /* V86 interface structure */
void __v86int(void);
#define v86 __v86
#define v86int __v86int
extern u_int32_t __base;
extern u_int32_t __args;
#define PTOV(pa) ((caddr_t)(pa) - __base)
#define VTOP(va) ((vm_offset_t)(va) + __base)
#define VTOPSEG(va) (u_int16_t)(VTOP((caddr_t)va) >> 4)
#define VTOPOFF(va) (u_int16_t)(VTOP((caddr_t)va) & 0xf)
#define V86_CY(x) ((x) & PSL_C)
#define V86_ZR(x) ((x) & PSL_Z)
void __exit(int) __attribute__((__noreturn__));
void __exec(caddr_t, ...);
#endif /* !_BTXV86_H_ */

View File

@ -0,0 +1,85 @@
#
# Copyright (c) 1998 Robert Nordier
# All rights reserved.
#
# Redistribution and use in source and binary forms are freely
# permitted provided that the above copyright notice and this
# paragraph and the following disclaimer are duplicated in all
# such forms.
#
# This software is provided "AS IS" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantability and fitness for a particular
# purpose.
#
# $FreeBSD$
#
# BTX V86 interface.
#
#
# Globals.
#
.global __v86int
#
# Fields in V86 interface structure.
#
.set V86_CTL,0x0 # Control flags
.set V86_ADDR,0x4 # Int number/address
.set V86_ES,0x8 # V86 ES
.set V86_DS,0xc # V86 DS
.set V86_FS,0x10 # V86 FS
.set V86_GS,0x14 # V86 GS
.set V86_EAX,0x18 # V86 EAX
.set V86_ECX,0x1c # V86 ECX
.set V86_EDX,0x20 # V86 EDX
.set V86_EBX,0x24 # V86 EBX
.set V86_EFL,0x28 # V86 eflags
.set V86_EBP,0x2c # V86 EBP
.set V86_ESI,0x30 # V86 ESI
.set V86_EDI,0x34 # V86 EDI
#
# Other constants.
#
.set INT_V86,0x31 # Interrupt number
.set SIZ_V86,0x38 # Size of V86 structure
#
# V86 interface function.
#
__v86int: popl __v86ret # Save return address
pushl $__v86 # Push pointer
call __v86_swap # Load V86 registers
int $INT_V86 # To BTX
call __v86_swap # Load user registers
addl $0x4,%esp # Discard pointer
pushl __v86ret # Restore return address
ret # To user
#
# Swap V86 and user registers.
#
__v86_swap: xchgl %ebp,0x4(%esp,1) # Swap pointer, EBP
xchgl %eax,V86_EAX(%ebp) # Swap EAX
xchgl %ecx,V86_ECX(%ebp) # Swap ECX
xchgl %edx,V86_EDX(%ebp) # Swap EDX
xchgl %ebx,V86_EBX(%ebp) # Swap EBX
pushl %eax # Save
pushf # Put eflags
popl %eax # in EAX
xchgl %eax,V86_EFL(%ebp) # Swap
pushl %eax # Put EAX
popf # in eflags
movl 0x8(%esp,1),%eax # Load EBP
xchgl %eax,V86_EBP(%ebp) # Swap
movl %eax,0x8(%esp,1) # Save EBP
popl %eax # Restore
xchgl %esi,V86_ESI(%ebp) # Swap ESI
xchgl %edi,V86_EDI(%ebp) # Swap EDI
xchgl %ebp,0x4(%esp,1) # Swap pointer, EBP
ret # To caller
#
# V86 interface structure.
#
.comm __v86,SIZ_V86
.comm __v86ret,4

View File

@ -0,0 +1,18 @@
# $FreeBSD$
PROG= cdboot
STRIP=
BINMODE=${NOBINMODE}
MAN=
SRCS= ${PROG}.S
CFLAGS+=-I${.CURDIR}/../../i386/common
ORG= 0x0000
LDFLAGS=${LDFLAGS_BIN}
.include <bsd.prog.mk>
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.cdboot.S= ${CLANG_NO_IAS}

View File

@ -0,0 +1,805 @@
#
# Copyright (c) 2006 TAKAHASHI Yoshihiro <nyan@FreeBSD.org>
# Copyright (c) 2001 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.
#
# $FreeBSD$
#
# Basically, we first create a set of boot arguments to pass to the loaded
# binary. Then we attempt to load /boot/loader from the CD we were booted
# off of.
#
#include <bootargs.h>
#
# Memory locations.
#
.set STACK_OFF,0x6000 # Stack offset
.set LOAD_SEG,0x0700 # Load segment
.set LOAD_SIZE,2048 # Load size
.set DAUA,0x0584 # DA/UA
.set MEM_PAGE_SIZE,0x1000 # memory page size, 4k
.set MEM_ARG,0x900 # Arguments at start
.set MEM_ARG_BTX,0xa100 # Where we move them to so the
# BTX client can see them
.set MEM_ARG_SIZE,0x18 # Size of the arguments
.set MEM_BTX_ADDRESS,0x9000 # where BTX lives
.set MEM_BTX_ENTRY,0x9010 # where BTX starts to execute
.set MEM_BTX_OFFSET,MEM_PAGE_SIZE # offset of BTX in the loader
.set MEM_BTX_CLIENT,0xa000 # where BTX clients live
#
# PC98 machine type from sys/pc98/pc98/pc98_machdep.h
#
.set MEM_SYS, 0xa100 # System common area segment
.set PC98_MACHINE_TYPE, 0x0620 # PC98 machine type
.set EPSON_ID, 0x0624 # EPSON machine id
.set M_NEC_PC98, 0x0001
.set M_EPSON_PC98, 0x0002
.set M_NOT_H98, 0x0010
.set M_H98, 0x0020
.set M_NOTE, 0x0040
.set M_NORMAL, 0x1000
.set M_8M, 0x8000
#
# Signature Constants
#
.set SIG1_OFF,0x1fe # Signature offset
.set SIG2_OFF,0x7fe # Signature offset
#
# a.out header fields
#
.set AOUT_TEXT,0x04 # text segment size
.set AOUT_DATA,0x08 # data segment size
.set AOUT_BSS,0x0c # zero'd BSS size
.set AOUT_SYMBOLS,0x10 # symbol table
.set AOUT_ENTRY,0x14 # entry point
.set AOUT_HEADER,MEM_PAGE_SIZE # size of the a.out header
#
# Segment selectors.
#
.set SEL_SDATA,0x8 # Supervisor data
.set SEL_RDATA,0x10 # Real mode data
.set SEL_SCODE,0x18 # PM-32 code
.set SEL_SCODE16,0x20 # PM-16 code
#
# BTX constants
#
.set INT_SYS,0x30 # BTX syscall interrupt
#
# Constants for reading from the CD.
#
.set ERROR_TIMEOUT,0x90 # BIOS timeout on read
.set NUM_RETRIES,3 # Num times to retry
.set SECTOR_SIZE,0x800 # size of a sector
.set SECTOR_SHIFT,11 # number of place to shift
.set BUFFER_LEN,0x100 # number of sectors in buffer
.set MAX_READ,0xf800 # max we can read at a time
.set MAX_READ_SEC,MAX_READ >> SECTOR_SHIFT
.set MEM_READ_BUFFER,0x9000 # buffer to read from CD
.set MEM_VOLDESC,MEM_READ_BUFFER # volume descriptor
.set MEM_DIR,MEM_VOLDESC+SECTOR_SIZE # Lookup buffer
.set VOLDESC_LBA,0x10 # LBA of vol descriptor
.set VD_PRIMARY,1 # Primary VD
.set VD_END,255 # VD Terminator
.set VD_ROOTDIR,156 # Offset of Root Dir Record
.set DIR_LEN,0 # Offset of Dir Record length
.set DIR_EA_LEN,1 # Offset of EA length
.set DIR_EXTENT,2 # Offset of 64-bit LBA
.set DIR_SIZE,10 # Offset of 64-bit length
.set DIR_NAMELEN,32 # Offset of 8-bit name len
.set DIR_NAME,33 # Offset of dir name
#
# Program start.
#
.code16
.globl start
start: jmp main
.org 4
.ascii "IPL1 "
main: cld
/* Setup the stack */
xor %ax,%ax
mov %ax,%ss
mov $STACK_OFF,%sp
push %ecx
/* Setup graphic screen */
mov $0x42,%ah # 640x400
mov $0xc0,%ch
int $0x18
mov $0x40,%ah # graph on
int $0x18
/* Setup text screen */
mov $0x0a00,%ax # 80x25
int $0x18
mov $0x0c,%ah # text on
int $0x18
mov $0x13,%ah # cursor home
xor %dx,%dx
int $0x18
mov $0x11,%ah # cursor on
int $0x18
/* Setup keyboard */
mov $0x03,%ah
int $0x18
/* Transfer PC-9801 system common area */
xor %ax,%ax
mov %ax,%si
mov %ax,%ds
mov %ax,%di
mov $MEM_SYS,%ax
mov %ax,%es
mov $0x0600,%cx
rep
movsb
/* Transfer EPSON machine type */
mov $0xfd00,%ax
mov %ax,%ds
mov (0x804),%eax
and $0x00ffffff,%eax
mov %eax,%es:(EPSON_ID)
/* Set machine type to PC98_SYSTEM_PARAMETER */
call machine_check
/* Load cdboot */
xor %ax,%ax
mov %ax,%ds
mov $0x06,%ah /* Read data */
mov (DAUA),%al /* Read drive */
pop %ecx /* cylinder */
xor %dx,%dx /* head / sector */
mov $LOAD_SEG,%bx /* Load address */
mov %bx,%es
xor %bp,%bp
mov $LOAD_SIZE,%bx /* Load size */
int $0x1b
mov $msg_readerr,%si
jc error
/* Jump to cdboot */
ljmp $LOAD_SEG,$cdboot
#
# Set machine type to PC98_SYSTEM_PARAMETER.
#
machine_check: xor %edx,%edx
mov %dx,%ds
mov $MEM_SYS,%ax
mov %ax,%es
/* Wait V-SYNC */
vsync.1: inb $0x60,%al
test $0x20,%al
jnz vsync.1
vsync.2: inb $0x60,%al
test $0x20,%al
jz vsync.2
/* ANK 'A' font */
xor %al,%al
outb %al,$0xa1
mov $0x41,%al
outb %al,$0xa3
/* Get 'A' font from CG window */
push %ds
mov $0xa400,%ax
mov %ax,%ds
xor %eax,%eax
xor %bx,%bx
mov $4,%cx
font.1: add (%bx),%eax
add $4,%bx
loop font.1
pop %ds
cmp $0x6efc58fc,%eax
jnz m_epson
m_pc98: or $M_NEC_PC98,%edx
mov $0x0458,%bx
mov (%bx),%al
test $0x80,%al
jz m_not_h98
or $M_H98,%edx
jmp 1f
m_epson: or $M_EPSON_PC98,%edx
m_not_h98: or $M_NOT_H98,%edx
1: inb $0x42,%al
test $0x20,%al
jz 1f
or $M_8M,%edx
1: mov $0x0400,%bx
mov (%bx),%al
test $0x80,%al
jz 1f
or $M_NOTE,%edx
1: mov $PC98_MACHINE_TYPE,%bx
mov %edx,%es:(%bx)
ret
#
# Print out the error message at [SI], wait for a keypress, and then
# reboot the machine.
#
error: call putstr
mov $msg_keypress,%si
call putstr
xor %ax,%ax # Get keypress
int $0x18
xor %ax,%ax # CPU reset
outb %al,$0xf0
halt: hlt
jmp halt # Spin
#
# Display a null-terminated string at [SI].
#
# Trashes: AX, BX, CX, DX, SI, DI
#
putstr: push %ds
push %es
mov %cs,%ax
mov %ax,%ds
mov $0xa000,%ax
mov %ax,%es
mov cursor,%di
mov $0x00e1,%bx # Attribute
mov $160,%cx
putstr.0: lodsb
testb %al,%al
jz putstr.done
cmp $0x0d,%al
jz putstr.cr
cmp $0x0a,%al
jz putstr.lf
mov %bl,%es:0x2000(%di)
stosb
inc %di
jmp putstr.move
putstr.cr: xor %dx,%dx
mov %di,%ax
div %cx
sub %dx,%di
jmp putstr.move
putstr.lf: add %cx,%di
putstr.move: mov %di,%dx
mov $0x13,%ah # Move cursor
int $0x18
jmp putstr.0
putstr.done: mov %di,cursor
pop %es
pop %ds
ret
#
# Display a single char at [AL], but don't move a cursor.
#
putc: push %es
push %di
push %bx
mov $0xa000,%bx
mov %bx,%es
mov cursor,%di
mov $0xe1,%bl # Attribute
mov %bl,%es:0x2000(%di)
stosb
pop %bx
pop %di
pop %es
ret
msg_readerr: .asciz "Read Error\r\n"
msg_keypress: .asciz "\r\nPress any key to reboot\r\n"
/* Boot signature */
.org SIG1_OFF,0x90
.word 0xaa55 # Magic number
#
# cdboot
#
cdboot: mov %cs,%ax
mov %ax,%ds
xor %ax,%ax
mov %ax,%es
mov %es:(DAUA),%al # Save BIOS boot device
mov %al,drive
mov %cx,cylinder # Save BIOS boot cylinder
mov $msg_welcome,%si # %ds:(%si) -> welcome message
call putstr # display the welcome message
#
# Setup the arguments that the loader is expecting from boot[12]
#
mov $msg_bootinfo,%si # %ds:(%si) -> boot args message
call putstr # display the message
mov $MEM_ARG,%bx # %ds:(%bx) -> boot args
mov %bx,%di # %es:(%di) -> boot args
xor %eax,%eax # zero %eax
mov $(MEM_ARG_SIZE/4),%cx # Size of arguments in 32-bit
# dwords
rep # Clear the arguments
stosl # to zero
mov drive,%dl # Store BIOS boot device
mov %dl,%es:0x4(%bx) # in kargs->bootdev
or $KARGS_FLAGS_CD,%es:0x8(%bx) # kargs->bootflags |=
# KARGS_FLAGS_CD
#
# Load Volume Descriptor
#
mov $VOLDESC_LBA,%eax # Set LBA of first VD
load_vd: push %eax # Save %eax
mov $1,%dh # One sector
mov $MEM_VOLDESC,%ebx # Destination
call read # Read it in
cmpb $VD_PRIMARY,%es:(%bx) # Primary VD?
je have_vd # Yes
pop %eax # Prepare to
inc %eax # try next
cmpb $VD_END,%es:(%bx) # Last VD?
jne load_vd # No, read next
mov $msg_novd,%si # No VD
jmp error # Halt
have_vd: # Have Primary VD
#
# Try to look up the loader binary using the paths in the loader_paths
# array.
#
mov $loader_paths,%si # Point to start of array
lookup_path: push %si # Save file name pointer
call lookup # Try to find file
pop %di # Restore file name pointer
jnc lookup_found # Found this file
push %es
mov %cs,%ax
mov %ax,%es
xor %al,%al # Look for next
mov $0xffff,%cx # path name by
repnz # scanning for
scasb # nul char
pop %es
mov %di,%si # Point %si at next path
mov (%si),%al # Get first char of next path
or %al,%al # Is it double nul?
jnz lookup_path # No, try it.
mov $msg_failed,%si # Failed message
jmp error # Halt
lookup_found: # Found a loader file
#
# Load the binary into the buffer. Due to real mode addressing limitations
# we have to read it in 64k chunks.
#
mov %es:DIR_SIZE(%bx),%eax # Read file length
add $SECTOR_SIZE-1,%eax # Convert length to sectors
shr $SECTOR_SHIFT,%eax
cmp $BUFFER_LEN,%eax
jbe load_sizeok
mov $msg_load2big,%si # Error message
jmp error
load_sizeok: movzbw %al,%cx # Num sectors to read
mov %es:DIR_EXTENT(%bx),%eax # Load extent
xor %edx,%edx
mov %es:DIR_EA_LEN(%bx),%dl
add %edx,%eax # Skip extended
mov $MEM_READ_BUFFER,%ebx # Read into the buffer
load_loop: mov %cl,%dh
cmp $MAX_READ_SEC,%cl # Truncate to max read size
jbe load_notrunc
mov $MAX_READ_SEC,%dh
load_notrunc: sub %dh,%cl # Update count
push %eax # Save
call read # Read it in
pop %eax # Restore
add $MAX_READ_SEC,%eax # Update LBA
add $MAX_READ,%ebx # Update dest addr
jcxz load_done # Done?
jmp load_loop # Keep going
load_done:
#
# Turn on the A20 address line
#
xor %ax,%ax # Turn A20 on
outb %al,$0xf2
mov $0x02,%al
outb %al,$0xf6
#
# Relocate the loader and BTX using a very lazy protected mode
#
mov $msg_relocate,%si # Display the
call putstr # relocation message
mov %es:(MEM_READ_BUFFER+AOUT_ENTRY),%edi # %edi is the destination
mov $(MEM_READ_BUFFER+AOUT_HEADER),%esi # %esi is
# the start of the text
# segment
mov %es:(MEM_READ_BUFFER+AOUT_TEXT),%ecx # %ecx = length of the text
# segment
push %edi # Save entry point for later
lgdt gdtdesc # setup our own gdt
cli # turn off interrupts
mov %cr0,%eax # Turn on
or $0x1,%al # protected
mov %eax,%cr0 # mode
ljmp $SEL_SCODE,$pm_start # long jump to clear the
# instruction pre-fetch queue
.code32
pm_start: mov $SEL_SDATA,%ax # Initialize
mov %ax,%ds # %ds and
mov %ax,%es # %es to a flat selector
rep # Relocate the
movsb # text segment
add $(MEM_PAGE_SIZE - 1),%edi # pad %edi out to a new page
and $~(MEM_PAGE_SIZE - 1),%edi # for the data segment
mov MEM_READ_BUFFER+AOUT_DATA,%ecx # size of the data segment
rep # Relocate the
movsb # data segment
mov MEM_READ_BUFFER+AOUT_BSS,%ecx # size of the bss
xor %eax,%eax # zero %eax
add $3,%cl # round %ecx up to
shr $2,%ecx # a multiple of 4
rep # zero the
stosl # bss
mov MEM_READ_BUFFER+AOUT_ENTRY,%esi # %esi -> relocated loader
add $MEM_BTX_OFFSET,%esi # %esi -> BTX in the loader
mov $MEM_BTX_ADDRESS,%edi # %edi -> where BTX needs to go
movzwl 0xa(%esi),%ecx # %ecx -> length of BTX
rep # Relocate
movsb # BTX
ljmp $SEL_SCODE16,$pm_16 # Jump to 16-bit PM
.code16
pm_16: mov $SEL_RDATA,%ax # Initialize
mov %ax,%ds # %ds and
mov %ax,%es # %es to a real mode selector
mov %cr0,%eax # Turn off
and $~0x1,%al # protected
mov %eax,%cr0 # mode
ljmp $LOAD_SEG,$pm_end # Long jump to clear the
# instruction pre-fetch queue
pm_end: sti # Turn interrupts back on now
#
# Copy the BTX client to MEM_BTX_CLIENT
#
mov %cs,%ax
mov %ax,%ds
xor %ax,%ax
mov %ax,%es
mov $MEM_BTX_CLIENT,%di # Prepare to relocate
mov $btx_client,%si # the simple btx client
mov $(btx_client_end-btx_client),%cx # length of btx client
rep # Relocate the
movsb # simple BTX client
#
# Copy the boot[12] args to where the BTX client can see them
#
xor %ax,%ax
mov %ax,%ds
mov $MEM_ARG,%si # where the args are at now
mov $MEM_ARG_BTX,%di # where the args are moving to
mov $(MEM_ARG_SIZE/4),%cx # size of the arguments in longs
rep # Relocate
movsl # the words
#
# Save the entry point so the client can get to it later on
#
pop %eax # Restore saved entry point
stosl # and add it to the end of
# the arguments
#
# Now we just start up BTX and let it do the rest
#
mov $msg_jump,%si # Display the
call putstr # jump message
ljmp $0,$MEM_BTX_ENTRY # Jump to the BTX entry point
#
# Lookup the file in the path at [SI] from the root directory.
#
# Trashes: All but BX
# Returns: CF = 0 (success), BX = pointer to record
# CF = 1 (not found)
#
lookup: mov $VD_ROOTDIR+MEM_VOLDESC,%bx # Root directory record
push %bx
push %si
mov $msg_lookup,%si # Display lookup message
call putstr
pop %si
push %si
call putstr
mov $msg_lookup2,%si
call putstr
pop %si
pop %bx
lookup_dir: lodsb # Get first char of path
cmp $0,%al # Are we done?
je lookup_done # Yes
cmp $'/',%al # Skip path separator.
je lookup_dir
dec %si # Undo lodsb side effect
call find_file # Lookup first path item
jnc lookup_dir # Try next component
mov $msg_lookupfail,%si # Not found message
push %bx
call putstr
pop %bx
stc # Set carry
ret
lookup_done: mov $msg_lookupok,%si # Success message
push %bx
call putstr
pop %bx
clc # Clear carry
ret
#
# Lookup file at [SI] in directory whose record is at [BX].
#
# Trashes: All but returns
# Returns: CF = 0 (success), BX = pointer to record, SI = next path item
# CF = 1 (not found), SI = preserved
#
find_file: mov %es:DIR_EXTENT(%bx),%eax # Load extent
xor %edx,%edx
mov %es:DIR_EA_LEN(%bx),%dl
add %edx,%eax # Skip extended attributes
mov %eax,rec_lba # Save LBA
mov %es:DIR_SIZE(%bx),%eax # Save size
mov %eax,rec_size
xor %cl,%cl # Zero length
push %si # Save
ff.namelen: inc %cl # Update length
lodsb # Read char
cmp $0,%al # Nul?
je ff.namedone # Yes
cmp $'/',%al # Path separator?
jnz ff.namelen # No, keep going
ff.namedone: dec %cl # Adjust length and save
mov %cl,name_len
pop %si # Restore
ff.load: mov rec_lba,%eax # Load LBA
mov $MEM_DIR,%ebx # Address buffer
mov $1,%dh # One sector
call read # Read directory block
incl rec_lba # Update LBA to next block
ff.scan: mov %ebx,%edx # Check for EOF
sub $MEM_DIR,%edx
cmp %edx,rec_size
ja ff.scan.1
stc # EOF reached
ret
ff.scan.1: cmpb $0,%es:DIR_LEN(%bx) # Last record in block?
je ff.nextblock
push %si # Save
movzbw %es:DIR_NAMELEN(%bx),%si # Find end of string
ff.checkver: cmpb $'0',%es:DIR_NAME-1(%bx,%si) # Less than '0'?
jb ff.checkver.1
cmpb $'9',%es:DIR_NAME-1(%bx,%si) # Greater than '9'?
ja ff.checkver.1
dec %si # Next char
jnz ff.checkver
jmp ff.checklen # All numbers in name, so
# no version
ff.checkver.1: movzbw %es:DIR_NAMELEN(%bx),%cx
cmp %cx,%si # Did we find any digits?
je ff.checkdot # No
cmpb $';',%es:DIR_NAME-1(%bx,%si) # Check for semicolon
jne ff.checkver.2
dec %si # Skip semicolon
mov %si,%cx
mov %cl,%es:DIR_NAMELEN(%bx) # Adjust length
jmp ff.checkdot
ff.checkver.2: mov %cx,%si # Restore %si to end of string
ff.checkdot: cmpb $'.',%es:DIR_NAME-1(%bx,%si) # Trailing dot?
jne ff.checklen # No
decb %es:DIR_NAMELEN(%bx) # Adjust length
ff.checklen: pop %si # Restore
movzbw name_len,%cx # Load length of name
cmp %cl,%es:DIR_NAMELEN(%bx) # Does length match?
je ff.checkname # Yes, check name
ff.nextrec: add %es:DIR_LEN(%bx),%bl # Next record
adc $0,%bh
jmp ff.scan
ff.nextblock: subl $SECTOR_SIZE,rec_size # Adjust size
jnc ff.load # If subtract ok, keep going
ret # End of file, so not found
ff.checkname: lea DIR_NAME(%bx),%di # Address name in record
push %si # Save
repe cmpsb # Compare name
je ff.match # We have a winner!
pop %si # Restore
jmp ff.nextrec # Keep looking.
ff.match: add $2,%sp # Discard saved %si
clc # Clear carry
ret
#
# Load DH sectors starting at LBA EAX into [EBX].
#
# Trashes: EAX
#
read: push %es # Save
push %bp
push %dx
push %cx
push %ebx
mov %bx,%bp # Set destination address
and $0x000f,%bp
shr $4,%ebx
mov %bx,%es
xor %bx,%bx # Set read bytes
mov %dh,%bl
shl $SECTOR_SHIFT,%bx # 2048 bytes/sec
mov %ax,%cx # Set LBA
shr $16,%eax
mov %ax,%dx
read.retry: mov $0x06,%ah # BIOS device read
mov drive,%al
and $0x7f,%al
call twiddle # Entertain the user
int $0x1b # Call BIOS
jc read.fail # Worked?
pop %ebx # Restore
pop %cx
pop %dx
pop %bp
pop %es
ret # Return
read.fail: cmp $ERROR_TIMEOUT,%ah # Timeout?
je read.retry # Yes, Retry.
read.error: mov %ah,%al # Save error
mov $hex_error,%di # Format it
call hex8 # as hex
mov $msg_badread,%si # Display Read error message
jmp error
#
# Output the "twiddle"
#
twiddle: push %ax # Save
push %bx # Save
mov twiddle_index,%al # Load index
mov $twiddle_chars,%bx # Address table
inc %al # Next
and $3,%al # char
mov %al,twiddle_index # Save index for next call
xlat # Get char
call putc # Output it
pop %bx # Restore
pop %ax # Restore
ret
#
# Convert AL to hex, saving the result to [EDI].
#
hex8: pushl %eax # Save
shrb $0x4,%al # Do upper
call hex8.1 # 4
popl %eax # Restore
hex8.1: andb $0xf,%al # Get lower 4
cmpb $0xa,%al # Convert
sbbb $0x69,%al # to hex
das # digit
orb $0x20,%al # To lower case
mov %al,(%di) # Save char
inc %di
ret # (Recursive)
#
# BTX client to start btxldr
#
.code32
btx_client: mov $(MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE-4), %esi
# %ds:(%esi) -> end
# of boot[12] args
mov $(MEM_ARG_SIZE/4),%ecx # Number of words to push
std # Go backwards
push_arg: lodsl # Read argument
push %eax # Push it onto the stack
loop push_arg # Push all of the arguments
cld # In case anyone depends on this
pushl MEM_ARG_BTX-MEM_BTX_CLIENT+MEM_ARG_SIZE # Entry point of
# the loader
push %eax # Emulate a near call
mov $0x1,%eax # 'exec' system call
int $INT_SYS # BTX system call
btx_client_end:
.code16
.p2align 4
#
# Global descriptor table.
#
gdt: .word 0x0,0x0,0x0,0x0 # Null entry
.word 0xffff,0x0000,0x9200,0x00cf # SEL_SDATA
.word 0xffff,0x0000,0x9200,0x0000 # SEL_RDATA
.word 0xffff,LOAD_SEG<<4,0x9a00,0x00cf # SEL_SCODE (32-bit)
.word 0xffff,LOAD_SEG<<4,0x9a00,0x008f # SEL_SCODE16 (16-bit)
gdt.1:
#
# Pseudo-descriptors.
#
gdtdesc: .word gdt.1-gdt-1 # Limit
.long LOAD_SEG<<4 + gdt # Base
#
# BOOT device
#
drive: .byte 0
cylinder: .word 0
#
# State for searching dir
#
rec_lba: .long 0x0 # LBA (adjusted for EA)
rec_size: .long 0x0 # File size
name_len: .byte 0x0 # Length of current name
cursor: .word 0
twiddle_index: .byte 0x0
msg_welcome: .asciz "CD Loader 1.2\r\n\n"
msg_bootinfo: .asciz "Building the boot loader arguments\r\n"
msg_relocate: .asciz "Relocating the loader and the BTX\r\n"
msg_jump: .asciz "Starting the BTX loader\r\n"
msg_badread: .ascii "Read Error: 0x"
hex_error: .asciz "00\r\n"
msg_novd: .asciz "Could not find Primary Volume Descriptor\r\n"
msg_lookup: .asciz "Looking up "
msg_lookup2: .asciz "... "
msg_lookupok: .asciz "Found\r\n"
msg_lookupfail: .asciz "File not found\r\n"
msg_load2big: .asciz "File too big\r\n"
msg_failed: .asciz "Boot failed\r\n"
twiddle_chars: .ascii "|/-\\"
loader_paths: .asciz "/BOOT.PC98/LOADER"
.asciz "/boot.pc98/loader"
.asciz "/BOOT/LOADER"
.asciz "/boot/loader"
.byte 0
/* Boot signature */
.org SIG2_OFF,0x90
.word 0xaa55 # Magic number

View File

@ -0,0 +1,20 @@
# $FreeBSD$
PROG= kgzldr.o
STRIP=
BINMODE=${LIBMODE}
BINDIR= ${LIBDIR}
MAN=
SRCS= start.s boot.c inflate.c lib.c crt.s sio.s
CFLAGS= -Os
CFLAGS+=-DKZIP
NO_SHARED=
LDFLAGS=-Wl,-r
.PATH: ${.CURDIR}/../../../kern
.PATH: ${.CURDIR}/../../i386/kgzldr
BOOT_COMCONSOLE_PORT?= 0x238
AFLAGS+=--defsym SIO_PRT=${BOOT_COMCONSOLE_PORT}
.include <bsd.prog.mk>

View File

@ -0,0 +1,89 @@
#
# Copyright (c) 1999 Global Technology Associates, Inc.
# 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.
#
# From: btx.s 1.10 1999/02/25 16:27:41 rnordier
# $FreeBSD$
#
# Screen defaults and assumptions.
.set SCR_MAT,0xe1 # Mode/attribute
.set SCR_COL,0x50 # Columns per row
.set SCR_ROW,0x19 # Rows per screen
# BIOS Data Area locations.
.set BDA_POS,0x53e # Cursor position
.globl crt_putchr
# void crt_putchr(int c)
crt_putchr: movb 0x4(%esp,1),%al # Get character
pusha # Save
xorl %ecx,%ecx # Zero for loops
movb $SCR_MAT,%ah # Mode/attribute
movl $BDA_POS,%ebx # BDA pointer
movw (%ebx),%dx # Cursor position
movl $0xa0000,%edi
crt_putchr.1: cmpb $0xa,%al # New line?
je crt_putchr.2 # Yes
movw %dx,%cx
movb %al,(%edi,%ecx,1) # Write char
addl $0x2000,%ecx
movb %ah,(%edi,%ecx,1) # Write attr
addw $0x02,%dx
jmp crt_putchr.3
crt_putchr.2: movw %dx,%ax
movb $SCR_COL*2,%dl
div %dl
incb %al
mul %dl
movw %ax,%dx
crt_putchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx
jb crt_putchr.4 # No
leal 2*SCR_COL(%edi),%esi # New top line
movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move
rep # Scroll
movsl # screen
movb $' ',%al # Space
xorb %ah,%ah
movb $SCR_COL,%cl # Columns to clear
rep # Clear
stosw # line
movw $(SCR_ROW-1)*SCR_COL*2,%dx
crt_putchr.4: movw %dx,(%ebx) # Update position
shrw $1,%dx
crt_putchr.5: inb $0x60,%al # Move cursor
testb $0x04,%al
jz crt_putchr.5
movb $0x49,%al
outb %al,$0x62
movb %dl,%al
outb %al,$0x60
movb %dh,%al
outb %al,$0x60
popa # Restore
ret # To caller

View File

@ -0,0 +1,51 @@
# $FreeBSD$
#
LIB= pc98
INTERNALLIB=
.PATH: ${.CURDIR}/../../i386/libi386
SRCS= bioscd.c biosdisk.c biosmem.c biospnp.c \
biospci.c biossmap.c bootinfo.c bootinfo32.c \
comconsole.c devicename.c elf32_freebsd.c \
i386_copy.c i386_module.c nullconsole.c pc98_sys.c pxe.c pxetramp.s \
time.c vidconsole.c
.PATH: ${.CURDIR}/../../zfs
SRCS+= devicename_stubs.c
# Enable PXE TFTP or NFS support, not both.
.if defined(LOADER_TFTP_SUPPORT)
CFLAGS+= -DLOADER_TFTP_SUPPORT
.else
CFLAGS+= -DLOADER_NFS_SUPPORT
.endif
BOOT_COMCONSOLE_PORT?= 0x238
CFLAGS+= -DCOMPORT=${BOOT_COMCONSOLE_PORT}
BOOT_COMCONSOLE_SPEED?= 9600
CFLAGS+= -DCOMSPEED=${BOOT_COMCONSOLE_SPEED}
.ifdef(BOOT_BIOSDISK_DEBUG)
# Make the disk code more talkative
CFLAGS+= -DDISK_DEBUG
.endif
# Include simple terminal emulation (cons25-compatible)
CFLAGS+= -DTERM_EMU
# XXX: make alloca() useable
CFLAGS+= -Dalloca=__builtin_alloca
CFLAGS+= -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386 \
-I${.CURDIR}/../../common \
-I${.CURDIR}/../btx/lib \
-I${.CURDIR}/../../i386/libi386 \
-I${.CURDIR}/../../.. -I.
# the location of libstand
CFLAGS+= -I${.CURDIR}/../../../../lib/libstand/
# Handle FreeBSD specific %b and %D printf format specifiers
CFLAGS+= ${FORMAT_EXTENSIONS}
.include <bsd.lib.mk>

View File

@ -0,0 +1,420 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* Copyright (c) 2001 John H. 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* BIOS CD device handling for CD's that have been booted off of via no
* emulation booting as defined in the El Torito standard.
*
* Ideas and algorithms from:
*
* - FreeBSD libi386/biosdisk.c
*
*/
#include <stand.h>
#include <sys/param.h>
#include <machine/bootinfo.h>
#include <stdarg.h>
#include <bootstrap.h>
#include <btxv86.h>
#include "libi386.h"
#define BIOSCD_SECSIZE 2048
#define BUFSIZE (1 * BIOSCD_SECSIZE)
#define MAXBCDEV 1
/* Major numbers for devices we frontend for. */
#define ACDMAJOR 117
#define CDMAJOR 15
#ifdef DISK_DEBUG
# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
#else
# define DEBUG(fmt, args...)
#endif
struct specification_packet {
u_char sp_size;
u_char sp_bootmedia;
u_char sp_drive;
u_char sp_controller;
u_int sp_lba;
u_short sp_devicespec;
u_short sp_buffersegment;
u_short sp_loadsegment;
u_short sp_sectorcount;
u_short sp_cylsec;
u_char sp_head;
};
/*
* List of BIOS devices, translation from disk unit number to
* BIOS unit number.
*/
static struct bcinfo {
int bc_unit; /* BIOS unit number */
struct specification_packet bc_sp;
int bc_open; /* reference counter */
void *bc_bcache; /* buffer cache data */
} bcinfo [MAXBCDEV];
static int nbcinfo = 0;
#define BC(dev) (bcinfo[(dev)->d_unit])
static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
static int bc_init(void);
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
size_t size, char *buf, size_t *rsize);
static int bc_realstrategy(void *devdata, int flag, daddr_t dblk,
size_t size, char *buf, size_t *rsize);
static int bc_open(struct open_file *f, ...);
static int bc_close(struct open_file *f);
static int bc_print(int verbose);
struct devsw bioscd = {
"cd",
DEVT_CD,
bc_init,
bc_strategy,
bc_open,
bc_close,
noioctl,
bc_print,
NULL
};
/*
* Translate between BIOS device numbers and our private unit numbers.
*/
int
bc_bios2unit(int biosdev)
{
int i;
DEBUG("looking for bios device 0x%x", biosdev);
for (i = 0; i < nbcinfo; i++) {
DEBUG("bc unit %d is BIOS device 0x%x", i, bcinfo[i].bc_unit);
if (bcinfo[i].bc_unit == biosdev)
return(i);
}
return(-1);
}
int
bc_unit2bios(int unit)
{
if ((unit >= 0) && (unit < nbcinfo))
return(bcinfo[unit].bc_unit);
return(-1);
}
/*
* We can't quiz, we have to be told what device to use, so this functoin
* doesn't do anything. Instead, the loader calls bc_add() with the BIOS
* device number to add.
*/
static int
bc_init(void)
{
return (0);
}
int
bc_add(int biosdev)
{
if (nbcinfo >= MAXBCDEV)
return (-1);
bcinfo[nbcinfo].bc_unit = biosdev;
/* SCSI CD-ROM only */
if ((biosdev & 0xf0) != 0xa0)
return (-1);
if ((((uint32_t *)PTOV(0xA1460))[biosdev & 0x0f] & 0x1f) != 5)
return (-1);
printf("BIOS CD is cd%d\n", nbcinfo);
nbcinfo++;
bcache_add_dev(nbcinfo); /* register cd device in bcache */
return(0);
}
/*
* Print information about disks
*/
static int
bc_print(int verbose)
{
char line[80];
int i, ret = 0;
if (nbcinfo == 0)
return (0);
printf("%s devices:", bioscd.dv_name);
if ((ret = pager_output("\n")) != 0)
return (ret);
for (i = 0; i < nbcinfo; i++) {
sprintf(line, " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
if ((ret = pager_output(line)) != 0)
break;
}
return (ret);
}
/*
* Attempt to open the disk described by (dev) for use by (f).
*/
static int
bc_open(struct open_file *f, ...)
{
va_list ap;
struct i386_devdesc *dev;
va_start(ap, f);
dev = va_arg(ap, struct i386_devdesc *);
va_end(ap);
if (dev->d_unit >= nbcinfo) {
DEBUG("attempt to open nonexistent disk");
return(ENXIO);
}
BC(dev).bc_open++;
if (BC(dev).bc_bcache == NULL)
BC(dev).bc_bcache = bcache_allocate();
return(0);
}
static int
bc_close(struct open_file *f)
{
struct i386_devdesc *dev;
dev = (struct i386_devdesc *)f->f_devdata;
BC(dev).bc_open--;
if (BC(dev).bc_open == 0) {
bcache_free(BC(dev).bc_bcache);
BC(dev).bc_bcache = NULL;
}
return(0);
}
static int
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
char *buf, size_t *rsize)
{
struct bcache_devdata bcd;
struct i386_devdesc *dev;
dev = (struct i386_devdesc *)devdata;
bcd.dv_strategy = bc_realstrategy;
bcd.dv_devdata = devdata;
bcd.dv_cache = BC(dev).bc_bcache;
return (bcache_strategy(&bcd, rw, dblk, size, buf, rsize));
}
static int
bc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
char *buf, size_t *rsize)
{
struct i386_devdesc *dev;
int unit;
int blks;
#ifdef BD_SUPPORT_FRAGS
char fragbuf[BIOSCD_SECSIZE];
size_t fragsize;
fragsize = size % BIOSCD_SECSIZE;
#else
if (size % BIOSCD_SECSIZE)
return (EINVAL);
#endif
if (rw != F_READ)
return(EROFS);
dev = (struct i386_devdesc *)devdata;
unit = dev->d_unit;
blks = size / BIOSCD_SECSIZE;
if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
return (EINVAL);
dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
DEBUG("read %d from %lld to %p", blks, dblk, buf);
if (rsize)
*rsize = 0;
if (blks && bc_read(unit, dblk, blks, buf)) {
DEBUG("read error");
return (EIO);
}
#ifdef BD_SUPPORT_FRAGS
DEBUG("frag read %d from %lld+%d to %p",
fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf)) {
DEBUG("frag read error");
return(EIO);
}
bcopy(fragbuf, buf + (blks * BIOSCD_SECSIZE), fragsize);
#endif
if (rsize)
*rsize = size;
return (0);
}
/* Max number of sectors to bounce-buffer at a time. */
#define CD_BOUNCEBUF 8
static int
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
{
u_int maxfer, resid, result, retry, x;
caddr_t bbuf, p, xp;
int biosdev;
#ifdef DISK_DEBUG
int error;
#endif
/* Just in case some idiot actually tries to read -1 blocks... */
if (blks < 0)
return (-1);
/* If nothing to do, just return succcess. */
if (blks == 0)
return (0);
/* Decide whether we have to bounce */
if (VTOP(dest) >> 20 != 0) {
/*
* The destination buffer is above first 1MB of
* physical memory so we have to arrange a suitable
* bounce buffer.
*/
x = min(CD_BOUNCEBUF, (unsigned)blks);
bbuf = alloca(x * BIOSCD_SECSIZE);
maxfer = x;
} else {
bbuf = NULL;
maxfer = 0;
}
biosdev = bc_unit2bios(unit);
resid = blks;
p = dest;
while (resid > 0) {
if (bbuf)
xp = bbuf;
else
xp = p;
x = resid;
if (maxfer > 0)
x = min(x, maxfer);
/*
* Loop retrying the operation a couple of times. The BIOS
* may also retry.
*/
for (retry = 0; retry < 3; retry++) {
/* If retrying, reset the drive */
if (retry > 0) {
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
v86.eax = 0x0300 | biosdev;
v86int();
}
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
v86.eax = 0x0600 | (biosdev & 0x7f);
v86.ebx = x * BIOSCD_SECSIZE;
v86.ecx = dblk & 0xffff;
v86.edx = (dblk >> 16) & 0xffff;
v86.ebp = VTOPOFF(xp);
v86.es = VTOPSEG(xp);
v86int();
result = V86_CY(v86.efl);
if (result == 0)
break;
}
#ifdef DISK_DEBUG
error = (v86.eax >> 8) & 0xff;
#endif
DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
VTOP(p), result ? "failed" : "ok");
DEBUG("unit %d status 0x%x", unit, error);
if (bbuf != NULL)
bcopy(bbuf, p, x * BIOSCD_SECSIZE);
p += (x * BIOSCD_SECSIZE);
dblk += x;
resid -= x;
}
/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
return(0);
}
/*
* Return a suitable dev_t value for (dev).
*/
int
bc_getdev(struct i386_devdesc *dev)
{
int biosdev, unit, device;
int major;
int rootdev;
unit = dev->d_unit;
biosdev = bc_unit2bios(unit);
DEBUG("unit %d BIOS device %d", unit, biosdev);
if (biosdev == -1) /* not a BIOS device */
return(-1);
device = biosdev & 0xf0;
if (device == 0x80)
major = ACDMAJOR;
else if (device == 0xa0)
major = CDMAJOR;
else
return (-1);
unit = 0; /* XXX */
/* XXX: Assume partition 'a'. */
rootdev = MAKEBOOTDEV(major, 0, unit, 0);
DEBUG("dev is 0x%x\n", rootdev);
return(rootdev);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Obtain memory configuration information from the BIOS
*/
#include <stand.h>
#include "libi386.h"
#include "btxv86.h"
vm_offset_t memtop, memtop_copyin, high_heap_base;
uint32_t bios_basemem, bios_extmem, high_heap_size;
/*
* The minimum amount of memory to reserve in bios_extmem for the heap.
*/
#define HEAP_MIN (64 * 1024 * 1024)
void
bios_getmem(void)
{
bios_basemem = ((*(u_char *)PTOV(0xA1501) & 0x07) + 1) * 128 * 1024;
bios_extmem = *(u_char *)PTOV(0xA1401) * 128 * 1024 +
*(u_int16_t *)PTOV(0xA1594) * 1024 * 1024;
/* Set memtop to actual top of memory */
memtop = memtop_copyin = 0x100000 + bios_extmem;
/*
* If we have extended memory, use the last 3MB of 'extended' memory
* as a high heap candidate.
*/
if (bios_extmem >= HEAP_MIN) {
high_heap_size = HEAP_MIN;
high_heap_base = memtop - HEAP_MIN;
}
}

View File

@ -0,0 +1,38 @@
/*-
* Copyright (c) 2006 TAKAHASHI Yoshihiro <nyan@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <sys/param.h>
#include "libi386.h"
void
bios_addsmapdata(struct preloaded_file *kfp)
{
}

View File

@ -0,0 +1,367 @@
/*-
* Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <bootstrap.h>
#include <machine/cpufunc.h>
#include <dev/ic/ns16550.h>
#include <dev/pci/pcireg.h>
#include "libi386.h"
#define COMC_FMT 0x3 /* 8N1 */
#define COMC_TXWAIT 0x40000 /* transmit timeout */
#define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */
#define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */
#ifndef COMPORT
#define COMPORT 0x238
#endif
#ifndef COMSPEED
#define COMSPEED 9600
#endif
static void comc_probe(struct console *cp);
static int comc_init(int arg);
static void comc_putchar(int c);
static int comc_getchar(void);
static int comc_getspeed(void);
static int comc_ischar(void);
static int comc_parseint(const char *string);
static uint32_t comc_parse_pcidev(const char *string);
static int comc_pcidev_set(struct env_var *ev, int flags,
const void *value);
static int comc_pcidev_handle(uint32_t locator);
static int comc_port_set(struct env_var *ev, int flags,
const void *value);
static void comc_setup(int speed, int port);
static int comc_speed_set(struct env_var *ev, int flags,
const void *value);
static int comc_curspeed;
static int comc_port = COMPORT;
static uint32_t comc_locator;
struct console comconsole = {
"comconsole",
"serial port",
0,
comc_probe,
comc_init,
comc_putchar,
comc_getchar,
comc_ischar
};
static void
comc_probe(struct console *cp)
{
char intbuf[16];
char *cons, *env;
int speed, port;
uint32_t locator;
if (comc_curspeed == 0) {
comc_curspeed = COMSPEED;
/*
* Assume that the speed was set by an earlier boot loader if
* comconsole is already the preferred console.
*/
cons = getenv("console");
if ((cons != NULL && strcmp(cons, comconsole.c_name) == 0) ||
getenv("boot_multicons") != NULL) {
comc_curspeed = comc_getspeed();
}
env = getenv("comconsole_speed");
if (env != NULL) {
speed = comc_parseint(env);
if (speed > 0)
comc_curspeed = speed;
}
sprintf(intbuf, "%d", comc_curspeed);
unsetenv("comconsole_speed");
env_setenv("comconsole_speed", EV_VOLATILE, intbuf, comc_speed_set,
env_nounset);
env = getenv("comconsole_port");
if (env != NULL) {
port = comc_parseint(env);
if (port > 0)
comc_port = port;
}
sprintf(intbuf, "%d", comc_port);
unsetenv("comconsole_port");
env_setenv("comconsole_port", EV_VOLATILE, intbuf, comc_port_set,
env_nounset);
env = getenv("comconsole_pcidev");
if (env != NULL) {
locator = comc_parse_pcidev(env);
if (locator != 0)
comc_pcidev_handle(locator);
}
unsetenv("comconsole_pcidev");
env_setenv("comconsole_pcidev", EV_VOLATILE, env, comc_pcidev_set,
env_nounset);
}
comc_setup(comc_curspeed, comc_port);
}
static int
comc_init(int arg)
{
comc_setup(comc_curspeed, comc_port);
if ((comconsole.c_flags & (C_PRESENTIN | C_PRESENTOUT)) ==
(C_PRESENTIN | C_PRESENTOUT))
return (CMD_OK);
return (CMD_ERROR);
}
static void
comc_putchar(int c)
{
int wait;
for (wait = COMC_TXWAIT; wait > 0; wait--)
if (inb(comc_port + com_lsr) & LSR_TXRDY) {
outb(comc_port + com_data, (u_char)c);
break;
}
}
static int
comc_getchar(void)
{
return (comc_ischar() ? inb(comc_port + com_data) : -1);
}
static int
comc_ischar(void)
{
return (inb(comc_port + com_lsr) & LSR_RXRDY);
}
static int
comc_speed_set(struct env_var *ev, int flags, const void *value)
{
int speed;
if (value == NULL || (speed = comc_parseint(value)) <= 0) {
printf("Invalid speed\n");
return (CMD_ERROR);
}
if (comc_curspeed != speed)
comc_setup(speed, comc_port);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
return (CMD_OK);
}
static int
comc_port_set(struct env_var *ev, int flags, const void *value)
{
int port;
if (value == NULL || (port = comc_parseint(value)) <= 0) {
printf("Invalid port\n");
return (CMD_ERROR);
}
if (comc_port != port)
comc_setup(comc_curspeed, port);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
return (CMD_OK);
}
/*
* Input: bus:dev:func[:bar]. If bar is not specified, it is 0x10.
* Output: bar[24:16] bus[15:8] dev[7:3] func[2:0]
*/
static uint32_t
comc_parse_pcidev(const char *string)
{
char *p, *p1;
uint8_t bus, dev, func, bar;
uint32_t locator;
int pres;
pres = strtol(string, &p, 0);
if (p == string || *p != ':' || pres < 0 )
return (0);
bus = pres;
p1 = ++p;
pres = strtol(p1, &p, 0);
if (p == string || *p != ':' || pres < 0 )
return (0);
dev = pres;
p1 = ++p;
pres = strtol(p1, &p, 0);
if (p == string || (*p != ':' && *p != '\0') || pres < 0 )
return (0);
func = pres;
if (*p == ':') {
p1 = ++p;
pres = strtol(p1, &p, 0);
if (p == string || *p != '\0' || pres <= 0 )
return (0);
bar = pres;
} else
bar = 0x10;
locator = (bar << 16) | biospci_locator(bus, dev, func);
return (locator);
}
static int
comc_pcidev_handle(uint32_t locator)
{
char intbuf[64];
uint32_t port;
if (biospci_read_config(locator & 0xffff,
(locator & 0xff0000) >> 16, 2, &port) == -1) {
printf("Cannot read bar at 0x%x\n", locator);
return (CMD_ERROR);
}
if (!PCI_BAR_IO(port)) {
printf("Memory bar at 0x%x\n", locator);
return (CMD_ERROR);
}
port &= PCIM_BAR_IO_BASE;
sprintf(intbuf, "%d", port);
unsetenv("comconsole_port");
env_setenv("comconsole_port", EV_VOLATILE, intbuf,
comc_port_set, env_nounset);
comc_setup(comc_curspeed, port);
comc_locator = locator;
return (CMD_OK);
}
static int
comc_pcidev_set(struct env_var *ev, int flags, const void *value)
{
uint32_t locator;
int error;
if (value == NULL || (locator = comc_parse_pcidev(value)) <= 0) {
printf("Invalid pcidev\n");
return (CMD_ERROR);
}
if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) != 0 &&
comc_locator != locator) {
error = comc_pcidev_handle(locator);
if (error != CMD_OK)
return (error);
}
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
return (CMD_OK);
}
static void
comc_setup(int speed, int port)
{
static int TRY_COUNT = 1000000;
char intbuf[64];
int tries;
unsetenv("hw.uart.console");
comc_curspeed = speed;
comc_port = port;
if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) == 0)
return;
outb(comc_port + com_cfcr, CFCR_DLAB | COMC_FMT);
outb(comc_port + com_dlbl, COMC_BPS(speed) & 0xff);
outb(comc_port + com_dlbh, COMC_BPS(speed) >> 8);
outb(comc_port + com_cfcr, COMC_FMT);
outb(comc_port + com_mcr, MCR_RTS | MCR_DTR);
tries = 0;
do
inb(comc_port + com_data);
while (inb(comc_port + com_lsr) & LSR_RXRDY && ++tries < TRY_COUNT);
if (tries < TRY_COUNT) {
comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT);
sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed);
env_setenv("hw.uart.console", EV_VOLATILE, intbuf, NULL, NULL);
} else
comconsole.c_flags &= ~(C_PRESENTIN | C_PRESENTOUT);
}
static int
comc_parseint(const char *speedstr)
{
char *p;
int speed;
speed = strtol(speedstr, &p, 0);
if (p == speedstr || *p != '\0' || speed <= 0)
return (-1);
return (speed);
}
static int
comc_getspeed(void)
{
u_int divisor;
u_char dlbh;
u_char dlbl;
u_char cfcr;
cfcr = inb(comc_port + com_cfcr);
outb(comc_port + com_cfcr, CFCR_DLAB | cfcr);
dlbl = inb(comc_port + com_dlbl);
dlbh = inb(comc_port + com_dlbh);
outb(comc_port + com_cfcr, cfcr);
divisor = dlbh << 8 | dlbl;
/* XXX there should be more sanity checking. */
if (divisor == 0)
return (COMSPEED);
return (COMC_DIV2BPS(divisor));
}

View File

@ -0,0 +1,29 @@
/*-
* Copyright (c) 2009 TAKAHASHI Yoshihiro <nyan@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.
*
* $FreeBSD$
*/
void set_machine_type(void);

View File

@ -0,0 +1,78 @@
/*-
* Copyright (c) 2009 TAKAHASHI Yoshihiro <nyan@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.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <btxv86.h>
#include <machine/cpufunc.h>
#define _KERNEL
#include <pc98/pc98/pc98_machdep.h>
/*
* Set machine type to PC98_SYSTEM_PARAMETER.
*/
void
set_machine_type(void)
{
int i;
u_long ret, data;
/* PC98_SYSTEM_PARAMETER (0x501) */
ret = ((*(u_char *)PTOV(0xA1501)) & 0x08) >> 3;
/* Wait V-SYNC */
while (inb(0x60) & 0x20) {}
while (!(inb(0x60) & 0x20)) {}
/* ANK 'A' font */
outb(0xa1, 0x00);
outb(0xa3, 0x41);
/* M_NORMAL, use CG window (all NEC OK) */
for (i = data = 0; i < 4; i++)
data += *((u_long *)PTOV(0xA4000) + i); /* 0xa4000 */
if (data == 0x6efc58fc) /* DA data */
ret |= M_NEC_PC98;
else
ret |= M_EPSON_PC98;
ret |= (inb(0x42) & 0x20) ? M_8M : 0;
/* PC98_SYSTEM_PARAMETER(0x400) */
if ((*(u_char *)PTOV(0xA1400)) & 0x80)
ret |= M_NOTE;
if (ret & M_NEC_PC98) {
/* PC98_SYSTEM_PARAMETER(0x458) */
if ((*(u_char *)PTOV(0xA1458)) & 0x80)
ret |= M_H98;
else
ret |= M_NOT_H98;
} else
ret |= M_NOT_H98;
(*(u_long *)PTOV(0xA1620)) = ret;
}

View File

@ -0,0 +1,98 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <btxv86.h>
#include <machine/cpufunc.h>
#include "bootstrap.h"
#include "libi386.h"
static int bios_seconds(void);
/*
* Return the BIOS time-of-day value.
*
* XXX uses undocumented BCD support from libstand.
*/
static int
bios_seconds(void)
{
int hr, minute, sec;
unsigned char bios_time[6];
v86.ctl = 0;
v86.addr = 0x1c; /* int 0x1c, function 0 */
v86.eax = 0x0000;
v86.es = VTOPSEG(bios_time);
v86.ebx = VTOPOFF(bios_time);
v86int();
hr = bcd2bin(bios_time[3]);
minute = bcd2bin(bios_time[4]);
sec = bcd2bin(bios_time[5]);
return (hr * 3600 + minute * 60 + sec);
}
/*
* Return the time in seconds since the beginning of the day.
*/
time_t
time(time_t *t)
{
static time_t lasttime;
time_t now;
now = bios_seconds();
if (now < lasttime)
now += 24 * 3600;
lasttime = now;
if (t != NULL)
*t = now;
return(now);
}
/*
* Use the BIOS Wait function to pause for (period) microseconds.
*
* Resolution of this function is variable, but typically around
* 1ms.
*/
void
delay(int period)
{
int i;
period = (period + 500) / 1000;
for( ; period != 0 ; period--)
for(i=800;i != 0; i--)
outb(0x5f,0); /* wait 600ns */
}

View File

@ -0,0 +1,596 @@
/*-
* Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
* Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
* 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.
*
* Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <bootstrap.h>
#include <btxv86.h>
#include <machine/cpufunc.h>
#include "libi386.h"
#if KEYBOARD_PROBE
#include <machine/cpufunc.h>
static int probe_keyboard(void);
#endif
static void vidc_probe(struct console *cp);
static int vidc_init(int arg);
static void vidc_putchar(int c);
static int vidc_getchar(void);
static int vidc_ischar(void);
static int vidc_started;
#ifdef TERM_EMU
#define MAXARGS 8
#define DEFAULT_FGCOLOR 7
#define DEFAULT_BGCOLOR 0
void end_term(void);
void bail_out(int c);
void vidc_term_emu(int c);
void get_pos(void);
void curs_move(int x, int y);
void write_char(int c, int fg, int bg);
void scroll_up(int rows, int fg, int bg);
void CD(void);
void CM(void);
void HO(void);
static int args[MAXARGS], argc;
static int fg_c, bg_c, curx, cury;
static int esc;
#endif
static unsigned short *crtat, *Crtat;
static int row = 25, col = 80;
#ifdef TERM_EMU
static u_int8_t ibmpc_to_pc98[256] = {
0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9,
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3,
0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb,
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
};
#define at2pc98(fg_at, bg_at) ibmpc_to_pc98[((bg_at) << 4) | (fg_at)]
#endif /* TERM_EMU */
struct console vidconsole = {
"vidconsole",
"internal video/keyboard",
0,
vidc_probe,
vidc_init,
vidc_putchar,
vidc_getchar,
vidc_ischar
};
static void
vidc_probe(struct console *cp)
{
/* look for a keyboard */
#if KEYBOARD_PROBE
if (probe_keyboard())
#endif
{
cp->c_flags |= C_PRESENTIN;
}
/* XXX for now, always assume we can do BIOS screen output */
cp->c_flags |= C_PRESENTOUT;
}
static int
vidc_init(int arg)
{
int i, hw_cursor;
if (vidc_started && arg == 0)
return (0);
vidc_started = 1;
Crtat = (unsigned short *)PTOV(0xA0000);
while ((inb(0x60) & 0x04) == 0)
;
outb(0x62, 0xe0);
while ((inb(0x60) & 0x01) == 0)
;
hw_cursor = inb(0x62);
hw_cursor |= (inb(0x62) << 8);
inb(0x62);
inb(0x62);
inb(0x62);
crtat = Crtat + hw_cursor;
#ifdef TERM_EMU
/* Init terminal emulator */
end_term();
get_pos();
curs_move(curx, cury);
fg_c = DEFAULT_FGCOLOR;
bg_c = DEFAULT_BGCOLOR;
#endif
for (i = 0; i < 10 && vidc_ischar(); i++)
(void)vidc_getchar();
return (0); /* XXX reinit? */
}
static void
beep(void)
{
outb(0x37, 6);
delay(40000);
outb(0x37, 7);
}
#if 0
static void
vidc_biosputchar(int c)
{
unsigned short *cp;
int i, pos;
#ifdef TERM_EMU
*crtat = (c == 0x5c ? 0xfc : c);
*(crtat + 0x1000) = at2pc98(fg, bg);
#else
switch(c) {
case '\b':
crtat--;
break;
case '\r':
crtat -= (crtat - Crtat) % col;
break;
case '\n':
crtat += col;
break;
default:
*crtat = (c == 0x5c ? 0xfc : c);
*(crtat++ + 0x1000) = 0xe1;
break;
}
if (crtat >= Crtat + col * row) {
cp = Crtat;
for (i = 1; i < row; i++) {
bcopy((void *)(cp + col), (void *)cp, col * 2);
cp += col;
}
for (i = 0; i < col; i++) {
*cp++ = ' ';
}
crtat -= col;
}
pos = crtat - Crtat;
while ((inb(0x60) & 0x04) == 0) {}
outb(0x62, 0x49);
outb(0x60, pos & 0xff);
outb(0x60, pos >> 8);
#endif
}
#endif
static void
vidc_rawputchar(int c)
{
int i;
if (c == '\t')
/* lame tab expansion */
for (i = 0; i < 8; i++)
vidc_rawputchar(' ');
else {
/* Emulate AH=0eh (teletype output) */
switch(c) {
case '\a':
beep();
return;
case '\r':
curx = 0;
curs_move(curx, cury);
return;
case '\n':
cury++;
if (cury > 24) {
scroll_up(1, fg_c, bg_c);
cury--;
} else {
curs_move(curx, cury);
}
return;
case '\b':
if (curx > 0) {
curx--;
curs_move(curx, cury);
/* write_char(' ', fg_c, bg_c); XXX destructive(!) */
return;
}
return;
default:
write_char(c, fg_c, bg_c);
curx++;
if (curx > 79) {
curx = 0;
cury++;
}
if (cury > 24) {
curx = 0;
scroll_up(1, fg_c, bg_c);
cury--;
}
}
curs_move(curx, cury);
}
}
#ifdef TERM_EMU
/* Get cursor position on the screen. Result is in edx. Sets
* curx and cury appropriately.
*/
void
get_pos(void)
{
int pos = crtat - Crtat;
curx = pos % col;
cury = pos / col;
}
/* Move cursor to x rows and y cols (0-based). */
void
curs_move(int x, int y)
{
int pos;
pos = x + y * col;
crtat = Crtat + pos;
pos = crtat - Crtat;
while((inb(0x60) & 0x04) == 0) {}
outb(0x62, 0x49);
outb(0x60, pos & 0xff);
outb(0x60, pos >> 8);
curx = x;
cury = y;
#define isvisible(c) (((c) >= 32) && ((c) < 255))
if (!isvisible(*crtat & 0x00ff)) {
write_char(' ', fg_c, bg_c);
}
}
/* Scroll up the whole window by a number of rows. If rows==0,
* clear the window. fg and bg are attributes for the new lines
* inserted in the window.
*/
void
scroll_up(int rows, int fgcol, int bgcol)
{
unsigned short *cp;
int i;
if (rows == 0)
rows = 25;
cp = Crtat;
for (i = rows; i < row; i++) {
bcopy((void *)(cp + col), (void *)cp, col * 2);
cp += col;
}
for (i = 0; i < col; i++) {
*(cp + 0x1000) = at2pc98(fgcol, bgcol);
*cp++ = ' ';
}
}
/* Write character and attribute at cursor position. */
void
write_char(int c, int fgcol, int bgcol)
{
*crtat = (c == 0x5c ? 0xfc : (c & 0xff));
*(crtat + 0x1000) = at2pc98(fgcol, bgcol);
}
/**************************************************************/
/*
* Screen manipulation functions. They use accumulated data in
* args[] and argc variables.
*
*/
/* Clear display from current position to end of screen */
void
CD(void)
{
int pos;
get_pos();
for (pos = 0; crtat + pos <= Crtat + col * row; pos++) {
*(crtat + pos) = ' ';
*(crtat + pos + 0x1000) = at2pc98(fg_c, bg_c);
}
end_term();
}
/* Absolute cursor move to args[0] rows and args[1] columns
* (the coordinates are 1-based).
*/
void
CM(void)
{
if (args[0] > 0)
args[0]--;
if (args[1] > 0)
args[1]--;
curs_move(args[1], args[0]);
end_term();
}
/* Home cursor (left top corner) */
void
HO(void)
{
argc = 1;
args[0] = args[1] = 1;
CM();
}
/* Clear internal state of the terminal emulation code */
void
end_term(void)
{
esc = 0;
argc = -1;
}
/* Gracefully exit ESC-sequence processing in case of misunderstanding */
void
bail_out(int c)
{
char buf[16], *ch;
int i;
if (esc) {
vidc_rawputchar('\033');
if (esc != '\033')
vidc_rawputchar(esc);
for (i = 0; i <= argc; ++i) {
sprintf(buf, "%d", args[i]);
ch = buf;
while (*ch)
vidc_rawputchar(*ch++);
}
}
vidc_rawputchar(c);
end_term();
}
static void
get_arg(int c)
{
if (argc < 0)
argc = 0;
args[argc] *= 10;
args[argc] += c - '0';
}
/* Emulate basic capabilities of cons25 terminal */
void
vidc_term_emu(int c)
{
static int ansi_col[] = {
0, 4, 2, 6, 1, 5, 3, 7,
};
int t;
int i;
switch (esc) {
case 0:
switch (c) {
case '\033':
esc = c;
break;
default:
vidc_rawputchar(c);
break;
}
break;
case '\033':
switch (c) {
case '[':
esc = c;
args[0] = 0;
argc = -1;
break;
default:
bail_out(c);
break;
}
break;
case '[':
switch (c) {
case ';':
if (argc < 0) /* XXX */
argc = 0;
else if (argc + 1 >= MAXARGS)
bail_out(c);
else
args[++argc] = 0;
break;
case 'H':
if (argc < 0)
HO();
else if (argc == 1)
CM();
else
bail_out(c);
break;
case 'J':
if (argc < 0)
CD();
else
bail_out(c);
break;
case 'm':
if (argc < 0) {
fg_c = DEFAULT_FGCOLOR;
bg_c = DEFAULT_BGCOLOR;
}
for (i = 0; i <= argc; ++i) {
switch (args[i]) {
case 0: /* back to normal */
fg_c = DEFAULT_FGCOLOR;
bg_c = DEFAULT_BGCOLOR;
break;
case 1: /* bold */
fg_c |= 0x8;
break;
case 4: /* underline */
case 5: /* blink */
bg_c |= 0x8;
break;
case 7: /* reverse */
t = fg_c;
fg_c = bg_c;
bg_c = t;
break;
case 30: case 31: case 32: case 33:
case 34: case 35: case 36: case 37:
fg_c = ansi_col[args[i] - 30];
break;
case 39: /* normal */
fg_c = DEFAULT_FGCOLOR;
break;
case 40: case 41: case 42: case 43:
case 44: case 45: case 46: case 47:
bg_c = ansi_col[args[i] - 40];
break;
case 49: /* normal */
bg_c = DEFAULT_BGCOLOR;
break;
}
}
end_term();
break;
default:
if (isdigit(c))
get_arg(c);
else
bail_out(c);
break;
}
break;
default:
bail_out(c);
break;
}
}
#endif
static void
vidc_putchar(int c)
{
#ifdef TERM_EMU
vidc_term_emu(c);
#else
vidc_rawputchar(c);
#endif
}
static int
vidc_getchar(void)
{
if (vidc_ischar()) {
v86.ctl = 0;
v86.addr = 0x18;
v86.eax = 0x0;
v86int();
return (v86.eax & 0xff);
} else {
return (-1);
}
}
static int
vidc_ischar(void)
{
v86.ctl = 0;
v86.addr = 0x18;
v86.eax = 0x100;
v86int();
return ((v86.ebx >> 8) & 0x1);
}
#if KEYBOARD_PROBE
static int
probe_keyboard(void)
{
return (*(u_char *)PTOV(0xA1481) & 0x48);
}
#endif /* KEYBOARD_PROBE */

View File

@ -0,0 +1,99 @@
# $FreeBSD$
.include <src.opts.mk>
MK_SSP= no
MAN=
LOADER?= loader
PROG= ${LOADER}.sym
INTERNALPROG=
NEWVERSWHAT= "bootstrap loader" pc98
VERSION_FILE= ${.CURDIR}/../../i386/loader/version
# architecture-specific loader code
SRCS= main.c conf.c vers.c
.PATH: ${.CURDIR}/../../i386/loader
# Enable PXE TFTP or NFS support, not both.
.if defined(LOADER_TFTP_SUPPORT)
CFLAGS+= -DLOADER_TFTP_SUPPORT
.else
CFLAGS+= -DLOADER_NFS_SUPPORT
.endif
# Include bcache code.
HAVE_BCACHE= yes
# Enable PnP and ISA-PnP code.
HAVE_PNP= yes
HAVE_ISABUS= yes
.if ${MK_FORTH} != "no"
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl -I${.CURDIR}/../../ficl/i386
LIBFICL= ${.OBJDIR}/../../ficl/libficl.a
.endif
.if defined(LOADER_BZIP2_SUPPORT)
CFLAGS+= -DLOADER_BZIP2_SUPPORT
.endif
.if !defined(LOADER_NO_GZIP_SUPPORT)
CFLAGS+= -DLOADER_GZIP_SUPPORT
.endif
# Always add MI sources
.PATH: ${.CURDIR}/../../common
.include "${.CURDIR}/../../common/Makefile.inc"
CFLAGS+= -I${.CURDIR}/../../common
CFLAGS+= -I${.CURDIR}/../../i386
CFLAGS+= -I.
CLEANFILES= ${LOADER} ${LOADER}.bin loader.help
CFLAGS+= -Wall
LDFLAGS= -static -Ttext 0x0
# pc98 standalone support library
LIBPC98= ${.OBJDIR}/../libpc98/libpc98.a
CFLAGS+= -I${.CURDIR}/..
LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a
# BTX components
CFLAGS+= -I${.CURDIR}/../btx/lib
# Debug me!
#CFLAGS+= -g
#LDFLAGS+= -g
# Pick up ../Makefile.inc early.
.include <bsd.init.mk>
${LOADER}: ${LOADER}.bin ${BTXLDR} ${BTXKERN}
btxld -v -f aout -e ${LOADER_ADDRESS} -o ${.TARGET} -l ${BTXLDR} \
-b ${BTXKERN} ${LOADER}.bin
${LOADER}.bin: ${LOADER}.sym
cp ${.ALLSRC} ${.TARGET}
strip -R .comment -R .note ${.TARGET}
loader.help: help.common help.pc98
cat ${.ALLSRC} | awk -f ${.CURDIR}/../../common/merge_help.awk > ${.TARGET}
FILES= ${LOADER}
# XXX INSTALLFLAGS_loader= -b
FILESMODE_${LOADER}= ${BINMODE} -b
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
FILES+= ${.CURDIR}/../../i386/loader/loader.rc menu.rc
# XXX crt0.o needs to be first for pxeboot(8) to work
OBJS= ${BTXCRT}
DPADD= ${LIBFICL} ${LIBPC98} ${LIBSTAND}
LDADD= ${LIBFICL} ${LIBPC98} ${LIBSTAND}
.include <bsd.prog.mk>

116
sys/boot/pc98/loader/conf.c Normal file
View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include <bootstrap.h>
#include "libi386/libi386.h"
/*
* We could use linker sets for some or all of these, but
* then we would have to control what ended up linked into
* the bootstrap. So it's easier to conditionalise things
* here.
*
* XXX rename these arrays to be consistent and less namespace-hostile
*
* XXX as libi386 and biosboot merge, some of these can become linker sets.
*/
/* Exported for libstand */
struct devsw *devsw[] = {
&bioscd,
&biosdisk,
#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
&pxedisk,
#endif
NULL
};
struct fs_ops *file_system[] = {
&ufs_fsops,
&ext2fs_fsops,
&dosfs_fsops,
&cd9660_fsops,
#ifdef LOADER_NFS_SUPPORT
&nfs_fsops,
#endif
#ifdef LOADER_TFTP_SUPPORT
&tftp_fsops,
#endif
#ifdef LOADER_GZIP_SUPPORT
&gzipfs_fsops,
#endif
#ifdef LOADER_BZIP2_SUPPORT
&bzipfs_fsops,
#endif
&splitfs_fsops,
NULL
};
/* Exported for i386 only */
/*
* Sort formats so that those that can detect based on arguments
* rather than reading the file go first.
*/
extern struct file_format i386_elf;
extern struct file_format i386_elf_obj;
struct file_format *file_formats[] = {
&i386_elf,
&i386_elf_obj,
NULL
};
/*
* Consoles
*
* We don't prototype these in libi386.h because they require
* data structures from bootstrap.h as well.
*/
extern struct console vidconsole;
extern struct console comconsole;
extern struct console nullconsole;
struct console *consoles[] = {
&vidconsole,
&comconsole,
&nullconsole,
NULL
};
extern struct pnphandler isapnphandler;
extern struct pnphandler biospnphandler;
extern struct pnphandler biospcihandler;
struct pnphandler *pnphandlers[] = {
&biospnphandler, /* should go first, as it may set isapnp_readport */
&isapnphandler,
&biospcihandler,
NULL
};

View File

@ -0,0 +1,38 @@
################################################################################
# Treboot DReboot the system
reboot
Causes the system to immediately reboot.
################################################################################
# Theap DDisplay memory management statistics
heap
Requests debugging output from the heap manager. For debugging use
only.
################################################################################
# Tset Snum_ide_disks DSet the number of IDE disks
NOTE: this variable is deprecated, use root_disk_unit instead.
set num_ide_disks=<value>
When booting from a SCSI disk on a system with one or more IDE disks,
and where the IDE disks are the default boot device, it is necessary
to tell the kernel how many IDE disks there are in order to have it
correctly locate the SCSI disk you are booting from.
################################################################################
# Tset Sroot_disk_unit DForce the root disk unit number.
set root_disk_unit=<value>
If the code which detects the disk unit number for the root disk is
confused, eg. by a mix of SCSI and IDE disks, or IDE disks with
gaps in the sequence (eg. no primary slave), the unit number can be
forced by setting this variable.
################################################################################

322
sys/boot/pc98/loader/main.c Normal file
View File

@ -0,0 +1,322 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* MD bootstrap main() and assorted miscellaneous
* commands.
*/
#include <stand.h>
#include <stddef.h>
#include <string.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include "bootstrap.h"
#include "common/bootargs.h"
#include "libi386/libi386.h"
#include "libpc98/libpc98.h"
#include "btxv86.h"
CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE);
CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO);
CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS);
CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE);
/* Arguments passed in from the boot1/boot2 loader */
static struct bootargs *kargs;
static u_int32_t initial_howto;
static u_int32_t initial_bootdev;
static struct bootinfo *initial_bootinfo;
struct arch_switch archsw; /* MI/MD interface boundary */
static void extract_currdev(void);
static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
/* from vers.c */
extern char bootprog_info[];
/* XXX debugging */
extern char end[];
static void *heap_top;
static void *heap_bottom;
static uint64_t
pc98_loadaddr(u_int type, void *data, uint64_t addr)
{
struct stat st;
if (type == LOAD_ELF)
return (roundup(addr, PAGE_SIZE));
/* We cannot use 15M-16M area on pc98. */
if (type == LOAD_RAW && addr < 0x1000000 && stat(data, &st) == 0 &&
(st.st_size == -1 || addr + st.st_size > 0xf00000))
addr = 0x1000000;
return (addr);
}
int
main(void)
{
int i;
/* Set machine type to PC98_SYSTEM_PARAMETER. */
set_machine_type();
/* Pick up arguments */
kargs = (void *)__args;
initial_howto = kargs->howto;
initial_bootdev = kargs->bootdev;
initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL;
/* Initialize the v86 register set to a known-good state. */
bzero(&v86, sizeof(v86));
v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
/*
* Initialise the heap as early as possible. Once this is done, malloc() is usable.
*/
bios_getmem();
#if defined(LOADER_BZIP2_SUPPORT)
if (high_heap_size > 0) {
heap_top = PTOV(high_heap_base + high_heap_size);
heap_bottom = PTOV(high_heap_base);
if (high_heap_base < memtop_copyin)
memtop_copyin = high_heap_base;
} else
#endif
{
heap_top = (void *)PTOV(bios_basemem);
heap_bottom = (void *)end;
}
setheap(heap_bottom, heap_top);
/*
* XXX Chicken-and-egg problem; we want to have console output early, but some
* console attributes may depend on reading from eg. the boot device, which we
* can't do yet.
*
* We can use printf() etc. once this is done.
* If the previous boot stage has requested a serial console, prefer that.
*/
bi_setboothowto(initial_howto);
if (initial_howto & RB_MULTIPLE) {
if (initial_howto & RB_SERIAL)
setenv("console", "comconsole vidconsole", 1);
else
setenv("console", "vidconsole comconsole", 1);
} else if (initial_howto & RB_SERIAL)
setenv("console", "comconsole", 1);
else if (initial_howto & RB_MUTE)
setenv("console", "nullconsole", 1);
cons_probe();
/*
* Initialise the block cache. Set the upper limit.
*/
bcache_init(32768, 512);
/*
* Special handling for PXE and CD booting.
*/
if (kargs->bootinfo == 0) {
/*
* We only want the PXE disk to try to init itself in the below
* walk through devsw if we actually booted off of PXE.
*/
if (kargs->bootflags & KARGS_FLAGS_PXE)
pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL);
else if (kargs->bootflags & KARGS_FLAGS_CD)
bc_add(initial_bootdev);
}
archsw.arch_autoload = i386_autoload;
archsw.arch_getdev = i386_getdev;
archsw.arch_copyin = i386_copyin;
archsw.arch_copyout = i386_copyout;
archsw.arch_readin = i386_readin;
archsw.arch_isainb = isa_inb;
archsw.arch_isaoutb = isa_outb;
archsw.arch_loadaddr = pc98_loadaddr;
/*
* March through the device switch probing for things.
*/
for (i = 0; devsw[i] != NULL; i++)
if (devsw[i]->dv_init != NULL)
(devsw[i]->dv_init)();
printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024);
if (initial_bootinfo != NULL) {
initial_bootinfo->bi_basemem = bios_basemem / 1024;
initial_bootinfo->bi_extmem = bios_extmem / 1024;
}
printf("\n%s", bootprog_info);
extract_currdev(); /* set $currdev and $loaddev */
setenv("LINES", "24", 1); /* optional */
interact(NULL); /* doesn't return */
/* if we ever get here, it is an error */
return (1);
}
/*
* Set the 'current device' by (if possible) recovering the boot device as
* supplied by the initial bootstrap.
*
* XXX should be extended for netbooting.
*/
static void
extract_currdev(void)
{
struct i386_devdesc new_currdev;
int major;
int biosdev = -1;
/* Assume we are booting from a BIOS disk by default */
new_currdev.d_dev = &biosdisk;
/* new-style boot loaders such as pxeldr and cdldr */
if (kargs->bootinfo == 0) {
if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
/* we are booting from a CD with cdboot */
new_currdev.d_dev = &bioscd;
new_currdev.d_unit = bc_bios2unit(initial_bootdev);
} else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
/* we are booting from pxeldr */
new_currdev.d_dev = &pxedisk;
new_currdev.d_unit = 0;
} else {
/* we don't know what our boot device is */
new_currdev.d_kind.biosdisk.slice = -1;
new_currdev.d_kind.biosdisk.partition = 0;
biosdev = -1;
}
} else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) {
/* The passed-in boot device is bad */
new_currdev.d_kind.biosdisk.slice = -1;
new_currdev.d_kind.biosdisk.partition = 0;
biosdev = -1;
} else {
new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1;
new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev);
biosdev = initial_bootinfo->bi_bios_dev;
major = B_TYPE(initial_bootdev);
/*
* If we are booted by an old bootstrap, we have to guess at the BIOS
* unit number. We will lose if there is more than one disk type
* and we are not booting from the lowest-numbered disk type
* (ie. SCSI when IDE also exists).
*/
if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) { /* biosdev doesn't match major */
if (B_TYPE(initial_bootdev) == 6)
biosdev = 0x30 + B_UNIT(initial_bootdev);
else
biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev);
}
}
new_currdev.d_type = new_currdev.d_dev->dv_type;
/*
* If we are booting off of a BIOS disk and we didn't succeed in determining
* which one we booted off of, just use disk0: as a reasonable default.
*/
if ((new_currdev.d_type == biosdisk.dv_type) &&
((new_currdev.d_unit = bd_bios2unit(biosdev)) == -1)) {
printf("Can't work out which disk we are booting from.\n"
"Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
new_currdev.d_unit = 0;
}
env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
i386_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset,
env_nounset);
}
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
command_reboot(int argc, char *argv[])
{
int i;
for (i = 0; devsw[i] != NULL; ++i)
if (devsw[i]->dv_cleanup != NULL)
(devsw[i]->dv_cleanup)();
printf("Rebooting...\n");
delay(1000000);
__exit(0);
}
/* provide this for panic, as it's not in the startup code */
void
exit(int code)
{
__exit(code);
}
COMMAND_SET(heap, "heap", "show heap usage", command_heap);
static int
command_heap(int argc, char *argv[])
{
mallocstats();
printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom,
sbrk(0), heap_top);
return(CMD_OK);
}
/* ISA bus access functions for PnP. */
static int
isa_inb(int port)
{
return (inb(port));
}
static void
isa_outb(int port, int value)
{
outb(port, value);
}

View File

@ -0,0 +1,25 @@
# $FreeBSD$
FILES= ${BOOT}
CLEANFILES= ${BOOT} ${BOOT}.part
BOOT= pc98boot
.if exists(${.OBJDIR}/../boot0)
BOOT0= ${.OBJDIR}/../boot0/boot0
.else
BOOT0= ${.CURDIR}/../boot0/boot0
.endif
.if exists(${.OBJDIR}/../boot0.5)
BOOT05= ${.OBJDIR}/../boot0.5/boot0.5
.else
BOOT05= ${.CURDIR}/../boot0.5/boot0.5
.endif
${BOOT}: ${BOOT0} ${BOOT05} ${BOOT}.part
cat ${BOOT0} ${BOOT}.part ${BOOT05} > ${.TARGET}
${BOOT}.part:
${DD} if=/dev/zero of=${.TARGET} bs=512 count=1
.include <bsd.prog.mk>

View File

@ -973,7 +973,7 @@ ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
errno = bwrite(bp);
if (errno != 0)
goto bad_ffs_write_file;
brelse(bp);
brelse(bp, 0);
if (!isfile)
p += chunk;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.c,v 1.12 2004/06/20 22:20:18 jmc Exp $ */
/* $NetBSD: buf.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -60,10 +60,12 @@ extern int sectorsize; /* XXX: from ffs.c & mkfs.c */
TAILQ_HEAD(buftailhead,buf) buftail;
int
bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp)
bread(struct vnode *vp, daddr_t blkno, int size, struct ucred *u1 __unused,
struct buf **bpp)
{
off_t offset;
ssize_t rv;
struct fs *fs = vp->fs;
assert (fs != NULL);
assert (bpp != NULL);
@ -71,7 +73,7 @@ bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp)
if (debug & DEBUG_BUF_BREAD)
printf("bread: fs %p blkno %lld size %d\n",
fs, (long long)blkno, size);
*bpp = getblk(fd, fs, blkno, size);
*bpp = getblk(vp, blkno, size, 0, 0, 0);
offset = (*bpp)->b_blkno * sectorsize; /* XXX */
if (debug & DEBUG_BUF_BREAD)
printf("bread: bp %p blkno %lld offset %lld bcount %ld\n",
@ -95,7 +97,7 @@ bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp)
}
void
brelse(struct buf *bp)
brelse(struct buf *bp, int u1 __unused)
{
assert (bp != NULL);
@ -174,12 +176,16 @@ bcleanup(void)
}
struct buf *
getblk(int fd, struct fs *fs, daddr_t blkno, int size)
getblk(struct vnode *vp, daddr_t blkno, int size, int u1 __unused,
int u2 __unused, int u3 __unused)
{
static int buftailinitted;
struct buf *bp;
void *n;
int fd = vp->fd;
struct fs *fs = vp->fs;
blkno += vp->offset;
assert (fs != NULL);
if (debug & DEBUG_BUF_GETBLK)
printf("getblk: fs %p blkno %lld size %d\n", fs,

View File

@ -1,4 +1,4 @@
/* $NetBSD: buf.h,v 1.2 2001/11/02 03:12:49 lukem Exp $ */
/* $NetBSD: buf.h,v 1.3 2001/11/02 03:12:49 lukem Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -43,6 +43,15 @@
#include <sys/param.h>
#include <sys/queue.h>
struct ucred;
struct vnode {
int fd;
void *fs;
void *v_data;
int offset;
};
struct buf {
void * b_data;
long b_bufsize;
@ -56,10 +65,11 @@ struct buf {
};
void bcleanup(void);
int bread(int, struct fs *, daddr_t, int, struct buf **);
void brelse(struct buf *);
int bread(struct vnode *, daddr_t, int, struct ucred *,
struct buf **);
void brelse(struct buf *, int);
int bwrite(struct buf *);
struct buf * getblk(int, struct fs *, daddr_t, int);
struct buf * getblk(struct vnode *, daddr_t, int, int, int, int);
#define bdwrite(bp) bwrite(bp)
#define clrbuf(bp) memset((bp)->b_data, 0, (u_int)(bp)->b_bcount)

View File

@ -297,19 +297,20 @@ ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
int error, frags, allocsiz, i;
struct fs *fs = ip->i_fs;
const int needswap = UFS_FSNEEDSWAP(fs);
struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
return (0);
error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)),
(int)fs->fs_cgsize, &bp);
error = bread(&vp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
NULL, &bp);
if (error) {
brelse(bp);
brelse(bp, 0);
return (0);
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic_swap(cgp, needswap) ||
(cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
brelse(bp);
brelse(bp, 0);
return (0);
}
if (size == fs->fs_bsize) {
@ -332,7 +333,7 @@ ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
* allocated, and hacked up
*/
if (cgp->cg_cs.cs_nbfree == 0) {
brelse(bp);
brelse(bp, 0);
return (0);
}
bno = ffs_alloccgblk(ip, bp, bpref);
@ -432,6 +433,7 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
int i, error, cg, blk, frags, bbase;
struct fs *fs = ip->i_fs;
const int needswap = UFS_FSNEEDSWAP(fs);
struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
if (size > fs->fs_bsize || fragoff(fs, size) != 0 ||
fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
@ -444,15 +446,15 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
(uintmax_t)ip->i_number);
return;
}
error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)),
(int)fs->fs_cgsize, &bp);
error = bread(&vp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
NULL, &bp);
if (error) {
brelse(bp);
brelse(bp, 0);
return;
}
cgp = (struct cg *)bp->b_data;
if (!cg_chkmagic_swap(cgp, needswap)) {
brelse(bp);
brelse(bp, 0);
return;
}
cgbno = dtogd(fs, bno);

View File

@ -89,6 +89,7 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
int32_t *allocblk, allociblk[NIADDR + 1];
int32_t *allocib;
const int needswap = UFS_FSNEEDSWAP(fs);
struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
lbn = lblkno(fs, offset);
size = blkoff(fs, offset) + bufsize;
@ -132,10 +133,10 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn,
fs->fs_bsize, bpp);
error = bread(&vp, lbn, fs->fs_bsize, NULL,
bpp);
if (error) {
brelse(*bpp);
brelse(*bpp, 0);
return (error);
}
}
@ -158,10 +159,10 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn,
osize, bpp);
error = bread(&vp, lbn, osize, NULL,
bpp);
if (error) {
brelse(*bpp);
brelse(*bpp, 0);
return (error);
}
}
@ -188,7 +189,7 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
if (error)
return (error);
if (bpp != NULL) {
bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
bp = getblk(&vp, lbn, nsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
clrbuf(bp);
*bpp = bp;
@ -226,7 +227,7 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
return error;
nb = newb;
*allocblk++ = nb;
bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
bp = getblk(&vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, nb);
clrbuf(bp);
/*
@ -244,10 +245,9 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
for (i = 1;;) {
error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
fs->fs_bsize, &bp);
error = bread(&vp, indirs[i].in_lbn, fs->fs_bsize, NULL, &bp);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
bap = (int32_t *)bp->b_data;
@ -256,20 +256,19 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
break;
i++;
if (nb != 0) {
brelse(bp);
brelse(bp, 0);
continue;
}
if (pref == 0)
pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
nb = newb;
*allocblk++ = nb;
nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
fs->fs_bsize);
nbp = getblk(&vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
clrbuf(nbp);
/*
@ -278,7 +277,7 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if ((error = bwrite(nbp)) != 0) {
brelse(bp);
brelse(bp, 0);
return error;
}
bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
@ -294,13 +293,13 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
nb = newb;
*allocblk++ = nb;
if (bpp != NULL) {
nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
nbp = getblk(&vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
clrbuf(nbp);
*bpp = nbp;
@ -314,11 +313,11 @@ ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
bwrite(bp);
return (0);
}
brelse(bp);
brelse(bp, 0);
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
error = bread(&vp, lbn, (int)fs->fs_bsize, NULL, &nbp);
if (error) {
brelse(nbp);
brelse(nbp, 0);
return error;
}
*bpp = nbp;
@ -340,6 +339,7 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
int64_t *allocblk, allociblk[NIADDR + 1];
int64_t *allocib;
const int needswap = UFS_FSNEEDSWAP(fs);
struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
lbn = lblkno(fs, offset);
size = blkoff(fs, offset) + bufsize;
@ -383,10 +383,10 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn,
fs->fs_bsize, bpp);
error = bread(&vp, lbn, fs->fs_bsize, NULL,
bpp);
if (error) {
brelse(*bpp);
brelse(*bpp, 0);
return (error);
}
}
@ -409,10 +409,10 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn,
osize, bpp);
error = bread(&vp, lbn, osize, NULL,
bpp);
if (error) {
brelse(*bpp);
brelse(*bpp, 0);
return (error);
}
}
@ -439,7 +439,7 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
if (error)
return (error);
if (bpp != NULL) {
bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
bp = getblk(&vp, lbn, nsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, newb);
clrbuf(bp);
*bpp = bp;
@ -477,7 +477,7 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
return error;
nb = newb;
*allocblk++ = nb;
bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
bp = getblk(&vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0);
bp->b_blkno = fsbtodb(fs, nb);
clrbuf(bp);
/*
@ -495,10 +495,9 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
for (i = 1;;) {
error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
fs->fs_bsize, &bp);
error = bread(&vp, indirs[i].in_lbn, fs->fs_bsize, NULL, &bp);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
bap = (int64_t *)bp->b_data;
@ -507,20 +506,19 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
break;
i++;
if (nb != 0) {
brelse(bp);
brelse(bp, 0);
continue;
}
if (pref == 0)
pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
nb = newb;
*allocblk++ = nb;
nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
fs->fs_bsize);
nbp = getblk(&vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
clrbuf(nbp);
/*
@ -529,7 +527,7 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
*/
if ((error = bwrite(nbp)) != 0) {
brelse(bp);
brelse(bp, 0);
return error;
}
bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
@ -545,13 +543,13 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
if (error) {
brelse(bp);
brelse(bp, 0);
return error;
}
nb = newb;
*allocblk++ = nb;
if (bpp != NULL) {
nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
nbp = getblk(&vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp->b_blkno = fsbtodb(fs, nb);
clrbuf(nbp);
*bpp = nbp;
@ -565,11 +563,11 @@ ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
bwrite(bp);
return (0);
}
brelse(bp);
brelse(bp, 0);
if (bpp != NULL) {
error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
error = bread(&vp, lbn, (int)fs->fs_bsize, NULL, &nbp);
if (error) {
brelse(nbp);
brelse(nbp, 0);
return error;
}
*bpp = nbp;