Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

723 lines
17 KiB

#include "insignia.h"
#include "host_def.h"
/*
* SoftPC Revision 3.0
*
* Title : ROM init functions
*
* Author : Ade Brownlow
*
* NB : These functions are used by BOTH the c and assembler cpus.
* also note that host_read_resource now returns a long.
*
* SCCS ID: @(#)rom.c 1.53 06/16/95
*
* (C) Copyright Insignia Solutions Ltd, 1994.
*/
#include <stdio.h>
#if defined(NTVDM) && defined(MONITOR)
#include <malloc.h>
#endif
#include TypesH
#include MemoryH
/*
* SoftPC include files
*/
#include "xt.h"
#include "sas.h"
#include CpuH
#include "error.h"
#include "config.h"
#include "rom.h"
#include "debug.h"
#include "ckmalloc.h"
#include "yoda.h"
#include "gispsvga.h"
#ifdef CPU_40_STYLE
#ifdef CCPU
#include "ccpusas4.h"
#else /* ! CCPU */
#include "Cpu_c.h"
#endif /* ! CCPU */
#endif /* CPU_40_STYLE */
#ifndef BIOS1ROM_FILENAME
#define BIOS1ROM_FILENAME "bios1.rom"
#endif /* BIOS1ROM_FILENAME */
#ifndef BIOS2ROM_FILENAME
#ifdef CPU_40_STYLE
#define BIOS2ROM_FILENAME "bios4.rom"
#else /* CPU_40_STYLE */
#define BIOS2ROM_FILENAME "bios2.rom"
#endif /* CPU_40_STYLE */
#endif /* BIOS2ROM_FILENAME */
#ifndef EGAROM_FILENAME
#define EGAROM_FILENAME "ega.rom"
#endif /* EGAROM_FILENAME */
#ifndef VGAROM_FILENAME
#define VGAROM_FILENAME "vga.rom"
#endif /* VGAROM_FILENAME */
#ifndef V7VGAROM_FILENAME
#define V7VGAROM_FILENAME "v7vga.rom"
#endif /* V7VGAROM_FILENAME */
#ifdef GISP_SVGA
#define GISP_VGAROM_FILENAME "hwvga.rom"
#define GISP_BIOS1ROM_FILENAME "hwbios1.rom"
#define GISP_BIOS2ROM_FILENAME BIOS2ROM_FILENAME
#endif
#ifndef ADAPTOR_ROM_START
#define ADAPTOR_ROM_START 0xc8000
#endif /* ADAPTOR_ROM_START */
#ifndef ADAPTOR_ROM_END
#define ADAPTOR_ROM_END 0xe0000
#endif /* ADAPTOR_ROM_END */
#define ADAPTOR_ROM_INCREMENT 0x800
#ifndef EXPANSION_ROM_START
#define EXPANSION_ROM_START 0xe0000
#endif /* EXPANSION_ROM_START */
#ifndef EXPANSION_ROM_END
#define EXPANSION_ROM_END 0xf0000
#endif /* EXPANSION_ROM_END */
#define EXPANSION_ROM_INCREMENT 0x10000
#define ROM_SIGNATURE 0xaa55
/* Current SoftPC verion number */
#define MAJOR_VER 0x03
#define MINOR_VER 0x00
#if defined(macintosh) && defined(A2CPU)
/* Buffer is temporarily allocted - no bigger than needed. */
#define ROM_BUFFER_SIZE 1024*25
#else
/* Using sas_scratch_buffer - will get 64K anyway. */
#define ROM_BUFFER_SIZE 1024*64
#endif
LOCAL LONG read_rom IPT2(char *, name, sys_addr, address);
LOCAL half_word do_rom_checksum IPT1(sys_addr, addr);
#ifdef ANSI
extern long host_read_resource (int, char *, host_addr, int ,int);
#else
extern long host_read_resource ();
#endif
/*(
*=========================== patchCheckSum ================================
* patchCheckSum
*
* Purpose
* This function calculates the check-sum for the indicated ROM,
* and patches it in at the indicated offset into the ROM.
*
* It also checks that the ROM has the correct signature, and length,
* and rounds the size up to a multiple of 512 bytes.
*
* Note this routine should not be called once paging is turned on.
*
* Input
* start Physical address of start of ROM
* length length of ROM in bytes
* offset Checksum byte offset from start.
*
* Outputs
* None.
*
* Description
* We round the size-up to a multiple of 512 bytes, check the
* signature, then patch-in the checksum.
)*/
LOCAL void
patchCheckSum IFN3(PHY_ADDR, start, PHY_ADDR, length, PHY_ADDR, offset)
{
PHY_ADDR roundedLength;
IU16 signature;
IU8 checksum;
IU8 *buffer;
PHY_ADDR currByte;
PHY_ADDR indicatedLength;
roundedLength = (length + 511) & (~511);
sas_connect_memory(start, start + roundedLength - 1, SAS_RAM);
#ifndef PROD
if (roundedLength != length) {
always_trace3("ROM at 0x%.5lx length rounded up from 0x%.8lx to 0x%.8lx", start, length, roundedLength);
}
if (roundedLength > (128 * 1024)) {
always_trace2("ROM at 0x%.5lx has a length of 0x%.8lx which is more than 128K", start, roundedLength);
force_yoda();
return;
}
if ((roundedLength <= offset) || (roundedLength < 4)) {
always_trace1("ROM at 0x%.5lx is too short!", start);
force_yoda();
return;
}
#endif
signature = sas_PR16(start);
if (signature != 0xaa55) {
always_trace2("ROM at 0x%.5lx has an invalid signature 0x%.4x (should be aa55)", start, signature);
sas_PW16(start, 0xaa55);
}
indicatedLength = sas_PR8(start + 2) * 512;
if (indicatedLength != roundedLength) {
always_trace3("ROM at 0x%.5lx has incorrect length 0x%.8lx (actually 0x%.8lx)", start, indicatedLength, roundedLength);
sas_PW8(start + 2, roundedLength / 512);
}
check_malloc(buffer, roundedLength, IU8);
sas_loads((LIN_ADDR)start, buffer, roundedLength);
checksum = 0;
for (currByte = 0; currByte < roundedLength; currByte++) {
checksum += buffer[currByte];
}
host_free(buffer);
if (checksum != 0) {
always_trace2("ROM at 0x%.8lx has incorrect checksum 0x%.2x",
start, checksum);
sas_PW8(start + offset,
(IU8)((IS8)sas_PR8(start + offset) - checksum));
}
sas_connect_memory(start, start + roundedLength - 1, SAS_ROM);
}
/*(
=============================== read_video_rom ============================
PURPOSE: Load the appropriate video rom file.
INPUT: None.
OUTPUT: None.
===========================================================================
)*/
GLOBAL void read_video_rom IFN0()
{
#ifdef REAL_VGA
read_rom (VGAROM_FILENAME, EGA_ROM_START);
#else /* REAL_VGA */
PHY_ADDR romLength = 0;
switch ((ULONG) config_inquire(C_GFX_ADAPTER, NULL))
{
#ifndef GISP_SVGA
#ifdef VGG
case VGA:
#ifdef V7VGA
romLength = read_rom (V7VGAROM_FILENAME, EGA_ROM_START);
#else /* V7VGA */
romLength = read_rom (VGAROM_FILENAME, EGA_ROM_START);
#endif /* V7VGA */
break;
#endif /* VGG */
#ifdef EGG
case EGA:
romLength = read_rom (EGAROM_FILENAME, EGA_ROM_START);
break;
#endif /* EGG */
default:
/* No rom required */
break;
#else /* GISP_SVGA */
/* GISP_SVGA - only have the gisp vga roms or, none for CGA boot */
case VGA:
romLength = read_rom (GISP_VGAROM_FILENAME, EGA_ROM_START);
default:
break;
#endif /* GISP_SVGA */
}
if (romLength != 0)
{
/* There is a problem with emm386 and Windows start up, which
* is cured by setting the video bios rom internal length
* to 32Kb.
* Is seems that the V86 manager (or emm386) incorrectly
* maps C6000..C7FFF during initialisation.
* We round up the video ROM to 32Kb to avoid this problem,
* which reduces the amount of "upper memory" RAM available to
* dos extenders by 12K.
*/
if (romLength < (32*1024))
romLength = (32*1024);
patchCheckSum(EGA_ROM_START, romLength, 5);
}
#endif /* not REAL_VGA */
}
GLOBAL void rom_init IFN0()
{
#if !defined(NTVDM) || ( defined(NTVDM) && !defined(X86GFX) )
/*
* Fill up all of ROM (Intel C0000 upwards) with bad op-codes.
* This is the Expansion ROM and the BIOS ROM.
* This will enable the CPU to trap any calls to ROM that are not made at a
* valid entry point.
*/
#ifdef GISP_SVGA
mapHostROMs( );
#else /* GISP_SVGA */
#if defined(macintosh) && defined(A2CPU)
/* not macintosh 2.0 cpus - they have sparse M */
#else
sas_fills( ROM_START, BAD_OP, PC_MEM_SIZE - ROM_START);
#endif /* macintosh && A2CPU */
#endif /* GISP_SVGA */
/*
* emm386 needs a hole to put it's page frame in.
*/
#if defined(SPC386) && !defined(GISP_CPU)
sas_connect_memory(0xc0000, 0xfffff, SAS_ROM);
#endif
/* Load the video rom. */
read_video_rom();
/* load the rom bios */
#ifdef GISP_SVGA
if ((ULONG) config_inquire(C_GFX_ADAPTER, NULL) == CGA )
{
read_rom (BIOS1ROM_FILENAME, BIOS_START);
read_rom (BIOS2ROM_FILENAME, BIOS2_START);
}
else
{
read_rom (GISP_BIOS1ROM_FILENAME, BIOS_START);
read_rom (GISP_BIOS2ROM_FILENAME, BIOS2_START);
}
#else /* GISP_SVGA */
read_rom (BIOS1ROM_FILENAME, BIOS_START);
read_rom (BIOS2ROM_FILENAME, BIOS2_START);
#endif /* GISP_SVGA */
#else /* !NTVDM | (NTVDM & !X86GFX) */
/*
* Now tell the CPU what it's not allowed to write over...
*
* These used to be done for everyone, but now they're only done for NT
* as everyone else should have done it inside read_rom.
*/
sas_connect_memory (BIOS_START, 0xFFFFFL, SAS_ROM);
#ifdef EGG
sas_connect_memory (EGA_ROM_START, EGA_ROM_END-1, SAS_ROM);
#endif
#endif /* !NTVDM | (NTVDM & !X86GFX) */
host_rom_init();
}
LOCAL LONG read_rom IFN2(char *, name, sys_addr, address)
{
#if !(defined(NTVDM) && defined(MONITOR))
host_addr tmp;
long size = 0;
/* do a rom load - use the sas_io buffer to get it the right way round */
/* BIOS rom first. */
/* Mac on 2.0 cpu doesn't want to use sas scratch buffer. */
#if defined(macintosh) && defined(A2CPU)
tmp = (host_addr)host_malloc(ROM_BUFFER_SIZE);
#else
tmp = (host_addr)sas_scratch_address(ROM_BUFFER_SIZE);
#endif
if (!tmp)
{
host_error(EG_MALLOC_FAILURE, ERR_CONT | ERR_QUIT, NULL);
return(0);
}
if (size = host_read_resource(ROMS_REZ_ID, name, tmp, ROM_BUFFER_SIZE, TRUE))
{
sas_connect_memory( address, address+size, SAS_RAM);
sas_stores (address, tmp, size);
sas_connect_memory( address, address+size, SAS_ROM);
}
#if defined(macintosh) && defined(A2CPU)
host_free((char *)tmp);
#endif
return( size );
#else
return ( 0L );
#endif /* !(NTVDM && MONITOR) */
}
LOCAL half_word do_rom_checksum IFN1(sys_addr, addr)
{
LONG sum = 0;
sys_addr last_byte_addr;
last_byte_addr = addr + (sas_hw_at(addr+2)*512);
for (; addr<last_byte_addr; addr++)
sum += sas_hw_at(addr);
return( sum % 0x100 );
}
LOCAL VOID do_search_for_roms IFN3(sys_addr, start_addr,
sys_addr, end_addr, unsigned long, increment)
{
word signature;
half_word checksum;
sys_addr addr;
word savedCS;
word savedIP;
for ( addr = start_addr; addr < end_addr; addr += increment )
{
if ((signature = sas_w_at(addr)) == ROM_SIGNATURE)
{
if ((checksum = do_rom_checksum(addr)) == 0)
{
/*
Now point at address of init code.
*/
addr += 3;
/*
Fake a CALLF by pushing a return CS:IP.
This points at a BOP FE in the bios to
get us back into 'c'
*/
push_word( 0xfe00 );
push_word( 0x95a );
savedCS = getCS();
savedIP = getIP();
setCS((addr & 0xf0000) >> 4);
setIP((addr & 0xffff));
host_simulate();
setCS(savedCS);
setIP(savedIP);
assert1(NO, "Additional ROM located and initialised at 0x%x ", addr-3);
}
else
{
assert2(NO, "Bad additonal ROM located at 0x%x, checksum = 0x%x\n", addr, checksum);
}
}
}
}
GLOBAL void search_for_roms IFN0()
{
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX))
#ifndef GISP_SVGA
/*
First search for adaptor ROM modules
*/
do_search_for_roms(ADAPTOR_ROM_START,
ADAPTOR_ROM_END, ADAPTOR_ROM_INCREMENT);
/*
Now search for expansion ROM modules
*/
do_search_for_roms(EXPANSION_ROM_START,
EXPANSION_ROM_END, EXPANSION_ROM_INCREMENT);
#endif /* GISP_SVGA */
#endif /* !NTVDM | (NTVDM & !X86GFX) */
}
GLOBAL void rom_checksum IFN0()
{
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) )
patchCheckSum(BIOS_START, PC_MEM_SIZE - BIOS_START,
0xfffff - BIOS_START);
#endif /* !NTVDM | (NTVDM & !X86GFX) */
}
GLOBAL VOID patch_rom IFN2(sys_addr, addr, half_word, val)
{
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) )
UTINY old_val;
/*
* 4.0 style CPUs don't export this variable, and if sas hasn't been
* inited, then the sas_connect will drop out to yoda.
*/
#ifdef CPU_40_STYLE
IU8 *hostPtr;
/* TMM 14/2/95
* -----------
* What we are doing here is replacing the sas_connect() method of writing to ROM
* with the new approach of poking the values directly in there. See display_string()
* below for a more detiled discussion of the why's and wherefores.
*/
#ifdef macintosh
/* The Mac config system wants to call this routine before the
* CPU exists, so we'd better invent a Mac-specific IBOOL to
* make the symptom non-fatal - finding and fixing the cause
* is too hard.
*/
{
extern IBOOL SafeToCallSas;
if (!SafeToCallSas)
return;
}
#endif /* macintosh */
/* The page might not be present (Arrggghhhh!!!!!)
** so we can't do anything sensible and must give
** up. We print an error though.
*/
hostPtr = getPtrToPhysAddrByte (addr);
if (hostPtr == 0)
{
host_error(EG_OWNUP, ERR_QUIT, NULL);
return;
}
old_val = *hostPtr;
/* Optimisation - don't upset the world if the value is unchanged.
*/
if (old_val == val)
return;
*hostPtr = val;
/*
* Adjust the checksum value by new - old.
* val is now difference between new and old value.
* We don't do this for GISP_SVGA because the checksums are already
* screwed, and attempting to write to the real host system ROM would
* only make things worse!
*/
#ifndef GISP_SVGA
/* Now get the checksum at the end of the ROM */
hostPtr = getPtrToPhysAddrByte (0xFFFFFL);
if (hostPtr == 0)
{
host_error(EG_OWNUP, ERR_QUIT, NULL);
return;
}
/* Now set the checksum to the difference between the old and new values */
*hostPtr -= (val - old_val);
#endif /* GISP_SVGA */
#else /* CPU_40_STYLE */
/*
* 4.0 style CPUs don't export this variable, and if sas hasn't been
* inited, then the sas_connect will drop out to yoda.
*/
if (Length_of_M_area == 0)
return;
old_val = sas_hw_at( addr );
/* Optimisation - don't upset the world if the value is unchanged.
*/
if (old_val == val)
return;
sas_connect_memory (addr, addr, SAS_RAM);
sas_store (addr,val);
sas_connect_memory (addr, addr, SAS_ROM);
/*
* Adjust the checksum value by new - old.
* val is now difference between new and old value.
* We don't do this for GISP_SVGA because the checksums are already
* screwed, and attempting to write to the real host system ROM would
* only make things worse!
*/
#ifndef GISP_SVGA
val -= old_val;
old_val = sas_hw_at( 0xFFFFFL );
old_val -= val;
sas_connect_memory (0xFFFFFL, 0xFFFFFL, SAS_RAM);
sas_store (0xFFFFFL, old_val);
sas_connect_memory (0xFFFFFL, 0xFFFFFL, SAS_ROM);
#endif /* GISP_SVGA */
#endif /* CPU_40_STYLE */
#endif /* !NTVDM | (NTVDM & !X86GFX) */
}
#ifndef GISP_SVGA
/*
* These routines were used by 2.0 CPUs which performed
* post-write checks. Since all 3.0 and later CPUs do
* pre-write checks they're no longer needed.
*/
#if !(defined(NTVDM) & defined(MONITOR))
void update_romcopy IFN1(long, addr)
{
UNUSED( addr );
}
#endif
GLOBAL void copyROM IFN0()
{
}
#endif /* GISP_SVGA */
/*
* To enable our drivers to output messages generated from
* our bops we use a scratch area inside our rom.
*/
#ifndef GISP_SVGA
LOCAL sys_addr cur_loc = DOS_SCRATCH_PAD;
#else /* GISP_SVGA */
/* For GISP svga builds, we initialise from gispROMInit() */
sys_addr cur_loc;
#endif /* GISP_SVGA */
GLOBAL void display_string IFN1(char *, string_ptr)
{
#if !defined(NTVDM) || (defined(NTVDM) && !defined(X86GFX) )
/*
* Put the message "*string_ptr" in the ROM
* scratch area where the drivers know where
* to output it from.
*/
#ifdef CPU_40_STYLE
IU8 *hostPtr;
IU16 count;
IU32 endLinAddr;
/* In a paging environment, we must be careful as a
** the ROM area could have been copied and/or mapped
** as read only. We must alter the memory which is
** currently at the linear address of the ROM (whether
** that is actually our rom or a RAM copy of it). We
** must force this alteration despite any protection
** placed on the page by the Intel page tables.
*/
/* get a host pointer to the memory behind the required
** linear address.
*/
hostPtr = getPtrToLinAddrByte(cur_loc);
/* The page might not be present (Arrggghhhh!!!!!)
** so we can't do anything sensible and must give
** up. We print an error though.
*/
if (hostPtr == 0)
{
host_error(EG_OWNUP, ERR_QUIT, NULL);
return;
}
/* the area to be patched must lie entirely in one intel page for
** this method to be sure to work. So check it.
*/
endLinAddr = (cur_loc + strlen(string_ptr) + 2);
if (((endLinAddr ^ DOS_SCRATCH_PAD) > 0xfff) || (endLinAddr > DOS_SCRATCH_PAD_END))
{
#ifndef PROD
fprintf(trace_file, "*** Warning ***: patch string into ROM too long; tuncating string '%s'", string_ptr);
#endif
if ((DOS_SCRATCH_PAD_END ^ DOS_SCRATCH_PAD) > 0xfff)
{
/* The defined DOS scratch pad crosses a page
** boundary. must truncate to the page boundary,
** allowing for the '$' and terminating zero
*/
string_ptr[0xffd - (DOS_SCRATCH_PAD & 0xfff)] = '\0';
}
else
{
/* The string overflows the DOS scratch pad. We
** must truncate to the scrtach pad boundary,
** allowing for the '$' and terminating zero
*/
string_ptr[cur_loc - DOS_SCRATCH_PAD - 2] = '\0';
}
}
for (count = 0; count < strlen(string_ptr); count++)
{
*IncCpuPtrLS8(hostPtr) = string_ptr[count];
}
/* Terminate the string */
*IncCpuPtrLS8(hostPtr) = '$';
*IncCpuPtrLS8(hostPtr) = '\0';
#else /* CPU_40_STYLE */
sas_connect_memory(DOS_SCRATCH_PAD, DOS_SCRATCH_PAD_END, SAS_RAM);
sas_stores(cur_loc, (host_addr)string_ptr, strlen(string_ptr));
cur_loc += strlen(string_ptr);
/* Terminate the string */
sas_store(cur_loc, '$');
sas_store(cur_loc + 1, '\0');
sas_disconnect_memory(DOS_SCRATCH_PAD, DOS_SCRATCH_PAD_END);
cur_loc -= strlen(string_ptr);
#endif /* CPU_40_STYLE */
#endif /* !NTVDM | !MONITOR */
cur_loc+=strlen(string_ptr);
}
GLOBAL void clear_string IFN0()
{
cur_loc = DOS_SCRATCH_PAD; /* Need to reset this pointer to start of **
** scratch area to prevent messages being **
** repeatedly displayed. */
display_string ("");
}
/* Returns the SoftPC version to our device drivers */
GLOBAL void softpc_version IFN0()
{
setAH(MAJOR_VER);
setAL(MINOR_VER);
}