- remove trailing white space, trailing empty lines, C++ comments, etc.
- split cmd_boot.c (separate cmd_bdinfo.c and cmd_load.c)
* Patches by Kenneth Johansson, 25 Jun 2003:
- major rework of command structure
(work done mostly by Michal Cendrowski and Joakim Kristiansen)
617 lines
14 KiB
C
617 lines
14 KiB
C
/*
|
|
* Copyright 1999 Egbert Eich
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of the authors not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. The authors makes no representations
|
|
* about the suitability of this software for any purpose. It is provided
|
|
* "as is" without express or implied warranty.
|
|
*
|
|
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
#define DELETE
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <sys/stat.h>
|
|
#if defined(__alpha__) || defined (__ia64__)
|
|
#include <sys/io.h>
|
|
#elif defined(HAVE_SYS_PERM)
|
|
#include <sys/perm.h>
|
|
#endif
|
|
#include "debug.h"
|
|
#include "v86bios.h"
|
|
#include "pci.h"
|
|
#include "AsmMacros.h"
|
|
|
|
#define SIZE 0x100000
|
|
#define VRAM_START 0xA0000
|
|
#define VRAM_SIZE 0x1FFFF
|
|
#define V_BIOS_SIZE 0x1FFFF
|
|
#define BIOS_START 0x7C00 /* default BIOS entry */
|
|
|
|
/*CARD8 code[] = { 0xb8 , 0xf0 , 0xf0, 0xf4 }; */
|
|
#define VB_X(x) (V_BIOS >> x) & 0xFF
|
|
CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xf4 };
|
|
/*CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xb8, 0x03, 0x00, */
|
|
/*0xcd, 0x10, 0xf4 }; */
|
|
/*CARD8 code[] = { 0xb8 , 0xf0 , 0xf0 ,0xf4 }; */
|
|
|
|
static void sig_handler(int);
|
|
static int map(void);
|
|
static void unmap(void);
|
|
static void bootBIOS(CARD16 ax);
|
|
static int map_vram(void);
|
|
static void unmap_vram(void);
|
|
static int copy_vbios(void);
|
|
static int copy_sys_bios(void);
|
|
static void save_bios_to_file(void);
|
|
static int setup_system_bios(void);
|
|
static void setup_int_vect(void);
|
|
static int chksum(CARD8 *start);
|
|
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax);
|
|
|
|
void loadCodeToMem(unsigned char *ptr, CARD8 *code);
|
|
void dprint(unsigned long start, unsigned long size);
|
|
|
|
static int vram_mapped = 0;
|
|
static CARD8 save_msr;
|
|
static CARD8 save_pos102;
|
|
static CARD8 save_vse;
|
|
static CARD8 save_46e8;
|
|
console Console;
|
|
struct config Config;
|
|
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
int Active_is_Pci = 0;
|
|
#ifdef DELETE
|
|
Config.PrintPort = PRINT_PORT;
|
|
Config.IoStatistics = IO_STATISTICS;
|
|
Config.PrintIrq = PRINT_IRQ;
|
|
Config.PrintPci = PRINT_PCI;
|
|
Config.ShowAllDev = SHOW_ALL_DEV;
|
|
Config.PrintIp = PRINT_IP;
|
|
Config.SaveBios = SAVE_BIOS;
|
|
Config.Trace = TRACE;
|
|
Config.ConfigActiveOnly = CONFIG_ACTIVE_ONLY;
|
|
Config.ConfigActiveDevice = CONFIG_ACTIVE_DEVICE;
|
|
Config.MapSysBios = MAP_SYS_BIOS;
|
|
Config.Resort = RESORT;
|
|
Config.FixRom = FIX_ROM;
|
|
Config.NoConsole = NO_CONSOLE;
|
|
Config.Verbose = VERBOSE;
|
|
|
|
if (!map())
|
|
exit(1);
|
|
|
|
if (!setup_system_bios())
|
|
exit(1);
|
|
|
|
iopl(3);
|
|
setup_io();
|
|
|
|
scan_pci();
|
|
if (!CurrentPci && !Config.ConfigActiveDevice && !Config.ConfigActiveOnly)
|
|
exit (1);
|
|
#endif
|
|
Console = open_console();
|
|
|
|
if (Config.ConfigActiveOnly) {
|
|
CARD16 ax;
|
|
int activePci = 0;
|
|
int error = 0;
|
|
|
|
while (CurrentPci) {
|
|
if (CurrentPci->active) {
|
|
activePci = 1;
|
|
if (!(mapPciRom(NULL) && chksum((CARD8*)V_BIOS)))
|
|
error = 1;
|
|
break;
|
|
}
|
|
CurrentPci = CurrentPci->next;
|
|
}
|
|
ax = ((CARD16)(CurrentPci->bus) << 8)
|
|
| (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
|
|
P_printf("ax: 0x%x\n",ax);
|
|
setup_int_vect();
|
|
if (!error && (activePci || copy_vbios())) {
|
|
|
|
if (Config.SaveBios) save_bios_to_file();
|
|
if (map_vram()) {
|
|
printf("initializing ISA\n");
|
|
bootBIOS(0);
|
|
}
|
|
}
|
|
unmap_vram();
|
|
sleep(1);
|
|
} else {
|
|
/* disable primary card */
|
|
save_msr = inb(0x3CC);
|
|
save_vse = inb(0x3C3);
|
|
save_46e8 = inb(0x46e8);
|
|
save_pos102 = inb(0x102);
|
|
|
|
signal(2,sig_handler);
|
|
signal(11,sig_handler);
|
|
|
|
outb(0x3C2,~(CARD8)0x03 & save_msr);
|
|
outb(0x3C3,~(CARD8)0x01 & save_vse);
|
|
outb(0x46e8, ~(CARD8)0x08 & save_46e8);
|
|
outb(0x102, ~(CARD8)0x01 & save_pos102);
|
|
|
|
pciVideoDisable();
|
|
|
|
while (CurrentPci) {
|
|
CARD16 ax;
|
|
|
|
if (CurrentPci->active) {
|
|
Active_is_Pci = 1;
|
|
if (!Config.ConfigActiveDevice) {
|
|
CurrentPci = CurrentPci->next;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
EnableCurrent();
|
|
|
|
if (CurrentPci->active) {
|
|
outb(0x102, save_pos102);
|
|
outb(0x46e8, save_46e8);
|
|
outb(0x3C3, save_vse);
|
|
outb(0x3C2, save_msr);
|
|
}
|
|
|
|
/* clear interrupt vectors */
|
|
setup_int_vect();
|
|
|
|
ax = ((CARD16)(CurrentPci->bus) << 8)
|
|
| (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
|
|
P_printf("ax: 0x%x\n",ax);
|
|
|
|
if (!((mapPciRom(NULL) && chksum((CARD8*)V_BIOS))
|
|
|| (CurrentPci->active && copy_vbios()))) {
|
|
CurrentPci = CurrentPci->next;
|
|
continue;
|
|
}
|
|
if (!map_vram()) {
|
|
CurrentPci = CurrentPci->next;
|
|
continue;
|
|
}
|
|
if (Config.SaveBios) save_bios_to_file();
|
|
printf("initializing PCI bus: %i dev: %i func: %i\n",CurrentPci->bus,
|
|
CurrentPci->dev,CurrentPci->func);
|
|
bootBIOS(ax);
|
|
unmap_vram();
|
|
|
|
CurrentPci = CurrentPci->next;
|
|
}
|
|
|
|
/* We have an ISA device - configure if requested */
|
|
if (!Active_is_Pci && Config.ConfigActiveDevice) {
|
|
pciVideoDisable();
|
|
|
|
outb(0x102, save_pos102);
|
|
outb(0x46e8, save_46e8);
|
|
outb(0x3C3, save_vse);
|
|
outb(0x3C2, save_msr);
|
|
|
|
setup_int_vect();
|
|
if (copy_vbios()) {
|
|
|
|
if (Config.SaveBios) save_bios_to_file();
|
|
if (map_vram()) {
|
|
printf("initializing ISA\n");
|
|
bootBIOS(0);
|
|
}
|
|
}
|
|
|
|
unmap_vram();
|
|
sleep(1);
|
|
}
|
|
|
|
pciVideoRestore();
|
|
|
|
outb(0x102, save_pos102);
|
|
outb(0x46e8, save_46e8);
|
|
outb(0x3C3, save_vse);
|
|
outb(0x3C2, save_msr);
|
|
}
|
|
|
|
close_console(Console);
|
|
#ifdef DELETE
|
|
iopl(0);
|
|
unmap();
|
|
|
|
printf("done !\n");
|
|
#endif
|
|
if (Config.IoStatistics)
|
|
io_statistics();
|
|
#ifdef DELETE
|
|
exit(0);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
map(void)
|
|
{
|
|
void* mem;
|
|
|
|
mem = mmap(0, (size_t)SIZE,
|
|
PROT_EXEC | PROT_READ | PROT_WRITE,
|
|
MAP_FIXED | MAP_PRIVATE | MAP_ANON,
|
|
-1, 0 );
|
|
if (mem != 0) {
|
|
perror("anonymous map");
|
|
return (0);
|
|
}
|
|
memset(mem,0,SIZE);
|
|
|
|
loadCodeToMem((unsigned char *) BIOS_START, code);
|
|
return (1);
|
|
}
|
|
|
|
static void
|
|
unmap(void)
|
|
{
|
|
munmap(0,SIZE);
|
|
}
|
|
|
|
static void
|
|
bootBIOS(CARD16 ax)
|
|
{
|
|
i86biosRegs bRegs;
|
|
#ifdef V86BIOS_DEBUG
|
|
printf("starting BIOS\n");
|
|
#endif
|
|
setup_bios_regs(&bRegs, ax);
|
|
do_x86(BIOS_START,&bRegs);
|
|
#ifdef V86BIOS_DEBUG
|
|
printf("done\n");
|
|
#endif
|
|
}
|
|
|
|
static int
|
|
map_vram(void)
|
|
{
|
|
int mem_fd;
|
|
|
|
#ifdef __ia64__
|
|
if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0)
|
|
#else
|
|
if ((mem_fd = open(MEM_FILE,O_RDWR))<0)
|
|
#endif
|
|
{
|
|
perror("opening memory");
|
|
return 0;
|
|
}
|
|
|
|
#ifndef __alpha__
|
|
if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE,
|
|
PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
|
|
mem_fd, VRAM_START) == (void *) -1)
|
|
#else
|
|
if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */
|
|
if (!_bus_base_sparse()) sparse_shift = 0;
|
|
if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift),
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_SHARED,
|
|
mem_fd, (VRAM_START << sparse_shift)
|
|
| _bus_base_sparse())) == (void *) -1)
|
|
#endif
|
|
{
|
|
perror("mmap error in map_hardware_ram");
|
|
close(mem_fd);
|
|
return (0);
|
|
}
|
|
vram_mapped = 1;
|
|
close(mem_fd);
|
|
return (1);
|
|
}
|
|
|
|
static void
|
|
unmap_vram(void)
|
|
{
|
|
if (!vram_mapped) return;
|
|
|
|
munmap((void*)VRAM_START,VRAM_SIZE);
|
|
vram_mapped = 0;
|
|
}
|
|
|
|
static int
|
|
copy_vbios(void)
|
|
{
|
|
int mem_fd;
|
|
unsigned char *tmp;
|
|
int size;
|
|
|
|
if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
|
|
perror("opening memory");
|
|
return (0);
|
|
}
|
|
|
|
if (lseek(mem_fd,(off_t) V_BIOS, SEEK_SET) != (off_t) V_BIOS) {
|
|
fprintf(stderr,"Cannot lseek\n");
|
|
goto Error;
|
|
}
|
|
tmp = (unsigned char *)malloc(3);
|
|
if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) {
|
|
fprintf(stderr,"Cannot read\n");
|
|
goto Error;
|
|
}
|
|
if (lseek(mem_fd,(off_t) V_BIOS,SEEK_SET) != (off_t) V_BIOS)
|
|
goto Error;
|
|
|
|
if (*tmp != 0x55 || *(tmp+1) != 0xAA ) {
|
|
#ifdef DEBUG
|
|
dprint((unsigned long)tmp,0x100);
|
|
#endif
|
|
fprintf(stderr,"No bios found at: 0x%x\n",V_BIOS);
|
|
goto Error;
|
|
}
|
|
size = *(tmp+2) * 512;
|
|
|
|
if (read(mem_fd, (char *)V_BIOS, (size_t) size) != (size_t) size) {
|
|
fprintf(stderr,"Cannot read\n");
|
|
goto Error;
|
|
}
|
|
free(tmp);
|
|
close(mem_fd);
|
|
if (!chksum((CARD8)V_BIOS))
|
|
return (0);
|
|
|
|
return (1);
|
|
|
|
Error:
|
|
perror("v_bios");
|
|
close(mem_fd);
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
copy_sys_bios(void)
|
|
{
|
|
#define SYS_BIOS 0xF0000
|
|
int mem_fd;
|
|
|
|
if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
|
|
perror("opening memory");
|
|
return (0);
|
|
}
|
|
|
|
if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS)
|
|
goto Error;
|
|
if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF)
|
|
goto Error;
|
|
|
|
close(mem_fd);
|
|
return (1);
|
|
|
|
Error:
|
|
perror("sys_bios");
|
|
close(mem_fd);
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
loadCodeToMem(unsigned char *ptr, CARD8 code[])
|
|
{
|
|
int i;
|
|
CARD8 val;
|
|
|
|
for ( i=0;;i++) {
|
|
val = code[i];
|
|
*ptr++ = val;
|
|
if (val == 0xf4) break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
void
|
|
dprint(unsigned long start, unsigned long size)
|
|
{
|
|
int i,j;
|
|
char *c = (char *)start;
|
|
|
|
for (j = 0; j < (size >> 4); j++) {
|
|
char *d = c;
|
|
printf("\n0x%lx: ",(unsigned long)c);
|
|
for (i = 0; i<16; i++)
|
|
printf("%2.2x ",(unsigned char) (*(c++)));
|
|
c = d;
|
|
for (i = 0; i<16; i++) {
|
|
printf("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ?
|
|
(unsigned char) (*(c)): '.');
|
|
c++;
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void
|
|
save_bios_to_file(void)
|
|
{
|
|
static int num = 0;
|
|
int size, count;
|
|
char file_name[256];
|
|
int fd;
|
|
|
|
sprintf(file_name,"bios_%i.fil",num);
|
|
if ((fd = open(file_name,O_WRONLY | O_CREAT | O_TRUNC,00644)) == -1)
|
|
return;
|
|
size = (*(unsigned char*)(V_BIOS + 2)) * 512;
|
|
#ifdef V86BIOS_DEBUG
|
|
dprint(V_BIOS,20);
|
|
#endif
|
|
if ((count = write(fd,(void *)(V_BIOS),size)) != size)
|
|
fprintf(stderr,"only saved %i of %i bytes\n",size,count);
|
|
num++;
|
|
}
|
|
|
|
static void
|
|
sig_handler(int unused)
|
|
{
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
|
|
/* put system back in a save state */
|
|
unmap_vram();
|
|
pciVideoRestore();
|
|
outb(0x102, save_pos102);
|
|
outb(0x46e8, save_46e8);
|
|
outb(0x3C3, save_vse);
|
|
outb(0x3C2, save_msr);
|
|
|
|
close_console(Console);
|
|
iopl(0);
|
|
unmap();
|
|
|
|
exit(1);
|
|
}
|
|
|
|
/*
|
|
* For initialization we just pass ax to the BIOS.
|
|
* PCI BIOSes need this. All other register are set 0.
|
|
*/
|
|
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax)
|
|
{
|
|
regs->ax = ax;
|
|
regs->bx = 0;
|
|
regs->cx = 0;
|
|
regs->dx = 0;
|
|
regs->es = 0;
|
|
regs->di = 0;
|
|
}
|
|
|
|
/*
|
|
* here we are really paranoid about faking a "real"
|
|
* BIOS. Most of this information was pulled from
|
|
* dosem.
|
|
*/
|
|
static void
|
|
setup_int_vect(void)
|
|
{
|
|
const CARD16 cs = 0x0000;
|
|
const CARD16 ip = 0x0;
|
|
int i;
|
|
|
|
/* let the int vects point to the SYS_BIOS seg */
|
|
for (i=0; i<0x80; i++) {
|
|
((CARD16*)0)[i<<1] = ip;
|
|
((CARD16*)0)[(i<<1)+1] = cs;
|
|
}
|
|
/* video interrupts default location */
|
|
((CARD16*)0)[(0x42<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x42<<1] = 0xf065;
|
|
((CARD16*)0)[(0x10<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x10<<1] = 0xf065;
|
|
/* video param table default location (int 1d) */
|
|
((CARD16*)0)[(0x1d<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x1d<<1] = 0xf0A4;
|
|
/* font tables default location (int 1F) */
|
|
((CARD16*)0)[(0x1f<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x1f<<1] = 0xfa6e;
|
|
|
|
/* int 11 default location */
|
|
((CARD16*)0)[(0x11<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x11<<1] = 0xf84d;
|
|
/* int 12 default location */
|
|
((CARD16*)0)[(0x12<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x12<<1] = 0xf841;
|
|
/* int 15 default location */
|
|
((CARD16*)0)[(0x15<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x15<<1] = 0xf859;
|
|
/* int 1A default location */
|
|
((CARD16*)0)[(0x1a<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x1a<<1] = 0xff6e;
|
|
/* int 05 default location */
|
|
((CARD16*)0)[(0x05<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x05<<1] = 0xff54;
|
|
/* int 08 default location */
|
|
((CARD16*)0)[(0x8<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x8<<1] = 0xfea5;
|
|
/* int 13 default location (fdd) */
|
|
((CARD16*)0)[(0x13<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x13<<1] = 0xec59;
|
|
/* int 0E default location */
|
|
((CARD16*)0)[(0xe<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0xe<<1] = 0xef57;
|
|
/* int 17 default location */
|
|
((CARD16*)0)[(0x17<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x17<<1] = 0xefd2;
|
|
/* fdd table default location (int 1e) */
|
|
((CARD16*)0)[(0x1e<<1)+1] = 0xf000;
|
|
((CARD16*)0)[0x1e<<1] = 0xefc7;
|
|
}
|
|
|
|
static int
|
|
setup_system_bios(void)
|
|
{
|
|
char *date = "06/01/99";
|
|
char *eisa_ident = "PCI/ISA";
|
|
|
|
#if MAP_SYS_BIOS
|
|
if (!copy_sys_bios()) return 0;
|
|
return 1;
|
|
#endif
|
|
/* memset((void *)0xF0000,0xf4,0xfff7); */
|
|
|
|
/*
|
|
* we trap the "industry standard entry points" to the BIOS
|
|
* and all other locations by filling them with "hlt"
|
|
* TODO: implement hlt-handler for these
|
|
*/
|
|
memset((void *)0xF0000,0xf4,0x10000);
|
|
|
|
/*
|
|
* TODO: we should copy the fdd table (0xfec59-0xfec5b)
|
|
* the video parameter table (0xf0ac-0xf0fb)
|
|
* and the font tables (0xfa6e-0xfe6d)
|
|
* from the original bios here
|
|
*/
|
|
|
|
/* set bios date */
|
|
strcpy((char *)0xFFFF5,date);
|
|
/* set up eisa ident string */
|
|
strcpy((char *)0xFFFD9,eisa_ident);
|
|
/* write system model id for IBM-AT */
|
|
((char *)0)[0xFFFFE] = 0xfc;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
chksum(CARD8 *start)
|
|
{
|
|
CARD16 size;
|
|
CARD8 val = 0;
|
|
int i;
|
|
|
|
size = *(start+2) * 512;
|
|
for (i = 0; i<size; i++)
|
|
val += *(start + i);
|
|
|
|
if (!val)
|
|
return 1;
|
|
|
|
fprintf(stderr,"BIOS cksum wrong!\n");
|
|
return 0;
|
|
}
|