summaryrefslogtreecommitdiffstats
path: root/private/ntos/boot/veneer
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/boot/veneer
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/boot/veneer')
-rw-r--r--private/ntos/boot/veneer/makefile6
-rw-r--r--private/ntos/boot/veneer/makefile.inc64
-rw-r--r--private/ntos/boot/veneer/ppc/pxcache.s139
-rw-r--r--private/ntos/boot/veneer/ppc/pxutil.s62
-rw-r--r--private/ntos/boot/veneer/ppc/sources36
-rw-r--r--private/ntos/boot/veneer/ppc/vrmp.s171
-rw-r--r--private/ntos/boot/veneer/ppc/vrstart.s116
-rw-r--r--private/ntos/boot/veneer/proto.h222
-rw-r--r--private/ntos/boot/veneer/sources49
-rw-r--r--private/ntos/boot/veneer/veneer.h287
-rw-r--r--private/ntos/boot/veneer/verno.c34
-rw-r--r--private/ntos/boot/veneer/vrbat.h112
-rw-r--r--private/ntos/boot/veneer/vrconfig.c567
-rw-r--r--private/ntos/boot/veneer/vrcons.c55
-rw-r--r--private/ntos/boot/veneer/vrcpiwrp.c525
-rw-r--r--private/ntos/boot/veneer/vrdisp.c169
-rw-r--r--private/ntos/boot/veneer/vrdumptr.c212
-rw-r--r--private/ntos/boot/veneer/vrenv.c254
-rw-r--r--private/ntos/boot/veneer/vrheader.h325
-rw-r--r--private/ntos/boot/veneer/vrio.c1425
-rw-r--r--private/ntos/boot/veneer/vrlib.c614
-rw-r--r--private/ntos/boot/veneer/vrload.c1035
-rw-r--r--private/ntos/boot/veneer/vrmain.c1314
-rw-r--r--private/ntos/boot/veneer/vrmalloc.c355
-rw-r--r--private/ntos/boot/veneer/vrmemory.c481
-rw-r--r--private/ntos/boot/veneer/vrmisc.c221
-rw-r--r--private/ntos/boot/veneer/vrpehdr.c138
-rw-r--r--private/ntos/boot/veneer/vrrstart.c274
-rw-r--r--private/ntos/boot/veneer/vrsup.c369
-rw-r--r--private/ntos/boot/veneer/vrtree.c2012
-rw-r--r--private/ntos/boot/veneer/vrtree.h153
31 files changed, 11796 insertions, 0 deletions
diff --git a/private/ntos/boot/veneer/makefile b/private/ntos/boot/veneer/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/boot/veneer/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/boot/veneer/makefile.inc b/private/ntos/boot/veneer/makefile.inc
new file mode 100644
index 000000000..b90118411
--- /dev/null
+++ b/private/ntos/boot/veneer/makefile.inc
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 1995,1996 FirePower Systems, Inc.
+#
+# $RCSfile: makefile.inc $
+# $Revision: 1.9 $
+# $Date: 1996/07/02 20:32:24 $
+# $Locker: $
+#
+
+!IFNDEF LANGUAGE
+LANGUAGE=usa
+!ENDIF
+
+!IFDEF NotNow
+msg.rc msg.h msg00001.bin: msg.$(LANGUAGE)
+ mc -v msg.$(LANGUAGE)
+!ENDIF
+
+!IF $(PPC)
+
+!IFDEF NotNow
+obj\$(TARGET_DIRECTORY)\veneer.res: msg.$(LANGUAGE)
+!ENDIF
+
+!IFNDEF DDKBUILDENV
+
+VENEER=obj\$(TARGET_DIRECTORY)\veneer.lib
+
+obj\$(TARGET_DIRECTORY)\veneer.exe: $(VENEER) makefile.inc
+ -link -out:obj\$(TARGET_DIRECTORY)\veneer.exe -nodefaultlib @<<
+-machine:$(TARGET_DIRECTORY)
+-rom
+-BASE:0x50000
+-debug:notmapped
+-debugtype:coff
+-map:obj\$(TARGET_DIRECTORY)\veneer.map
+-align:0x200
+-entry:start
+obj\$(TARGET_DIRECTORY)\veneer.lib
+$(BASEDIR)\public\sdk\lib\$(TARGET_DIRECTORY)\int64.lib
+<<NOKEEP
+
+
+ -@binplace obj\$(TARGET_DIRECTORY)\veneer.exe
+
+!ELSE
+#
+# This is for building within a DDK environment...
+#
+VENEER=$(BASEDIR)\lib\$(CPU)\$(DDKBUILDENV)\veneer.lib
+
+$(TARGETPATH)\$(TARGET_DIRECTORY)\veneer.exe: $(VENEER) makefile.inc
+ -link -out:$(TARGETPATH)\$(TARGET_DIRECTORY)\veneer.exe -nodefaultlib -machine:ppc -rom -BASE:0x50000 -debug:notmapped -debugtype:coff -map:obj\ppc\veneer.map -align:0x200 -entry:start $(VENEER) $(BASEDIR)\lib\$(TARGET_DIRECTORY)\$(DDKBUILDENV)\int64.lib
+# -@binplace -d .. $(TARGETPATH)\$(TARGET_DIRECTORY)\veneer.exe
+
+$(VENEER): obj\$(CPU)\$(DDKBUILDENV)\veneer.lib
+ -copy obj\$(CPU)\$(DDKBUILDENV)\veneer.lib $(VENEER)
+
+!ENDIF # End of else clause covering ddk build environment case
+
+verno.c: $(MAIN_PPC_SOURCES)
+
+!ENDIF # End of IF $(PPC) clause
+
diff --git a/private/ntos/boot/veneer/ppc/pxcache.s b/private/ntos/boot/veneer/ppc/pxcache.s
new file mode 100644
index 000000000..74fea4e71
--- /dev/null
+++ b/private/ntos/boot/veneer/ppc/pxcache.s
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: pxcache.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:54:50 $
+ * $Locker: $
+ *
+ * Derived from:
+ * Source: halfire/ppc/pxcache.s
+ * Revision: 1.6
+ * Date: 1995/04/17 21:17:37
+ */
+
+//++
+//
+// Copyright (c) 1993, 1994, 1995 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to pas,
+// added 604 support.
+// 18-Jan-95 plj Add 603+, 604+ and 620 support.
+//
+//--
+
+#include "kxppc.h"
+
+//++
+//
+// HalpSweepPhysicalRangeInBothCaches
+//
+// Force data in a given PHYSICAL address range to memory and
+// invalidate from the block in the instruction cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .set PAGE_SHIFT, 12
+
+
+ LEAF_ENTRY(HalpSweepPhysicalRangeInBothCaches)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspribc
+hspribc:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspribc.real - hspribc
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspribc.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspribc.loop:
+// XXX dcbst 0, r.4 // flush data block to memory
+ dcbf 0, r.4 // flush data block to memory
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspribc.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalRangeInBothCaches)
diff --git a/private/ntos/boot/veneer/ppc/pxutil.s b/private/ntos/boot/veneer/ppc/pxutil.s
new file mode 100644
index 000000000..e4f5b5f2f
--- /dev/null
+++ b/private/ntos/boot/veneer/ppc/pxutil.s
@@ -0,0 +1,62 @@
+//++
+//
+// Copyright (c) 1995 FirePower Systems, Inc.
+//
+// $RCSfile: pxutil.s $
+// $Revision: 1.6 $
+// $Date: 1996/01/11 07:54:54 $
+// $Locker: $
+//
+// Copyright (c) 1994 FirePower Systems, Inc.
+//
+//
+// Module Name:
+//
+// pxutil.s
+//
+//
+// Author:
+//
+// Shin Iwamoto at FirePower Systems, Inc.
+//
+//
+// Revision History:
+// 15-Sep-94 Shin Iwamoto at FirePower Systems, Inc.
+// Changed passing argument.
+// 06-Jul-94 Shin Iwamoto at FirePower Systems, Inc.
+// Created.
+//
+//--
+
+//++
+//
+// Routine Description:
+//
+// PxInvoke
+//
+// This function is called by FwInvoke and runs in FwInvoke's context.
+// That is, sp register isn't changed and link register is lost.
+//
+//
+//--
+ .text
+
+ .globl ..PxInvoke
+..PxInvoke:
+
+ mtspr ctr,r3 // load ctr reg. with routine to call
+
+ mr r3,r5 // move argc to 1st argument
+ mr r4,r6 // move argv to 2nd argument
+ mr r5,r7 // move envp to 3rd argument
+ bctr // jump to execute routine (no return)
+
+
+//
+// TOC entries
+//
+ .reldata
+ .align 2
+ .globl PxInvoke
+PxInvoke:
+ .long ..PxInvoke,.toc
diff --git a/private/ntos/boot/veneer/ppc/sources b/private/ntos/boot/veneer/ppc/sources
new file mode 100644
index 000000000..8bfd468c9
--- /dev/null
+++ b/private/ntos/boot/veneer/ppc/sources
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 1995 FirePower Systems, Inc.
+#
+# $RCSfile: sources $
+# $Revision: 1.4 $
+# $Date: 1996/01/11 07:54:58 $
+# $Locker: $
+#
+
+MAIN_PPC_SOURCES=\
+ vrmain.c \
+ vrconfig.c \
+ vrcons.c \
+ vrcpiwrp.c \
+ vrdumptr.c \
+ vrenv.c \
+ vrio.c \
+ vrdisp.c \
+ vrlib.c \
+ vrmalloc.c \
+ vrmemory.c \
+ vrload.c \
+ vrrstart.c \
+ vrmisc.c \
+ vrpehdr.c \
+ vrsup.c \
+ vrtree.c \
+ ppc\vrstart.s \
+ ppc\vrmp.s \
+ ppc\pxcache.s \
+ ppc\pxutil.s
+
+PPC_SOURCES=$(MAIN_PPC_SOURCES) \
+ verno.c
+
+NTTARGETFILES=obj\*\veneer.exe
diff --git a/private/ntos/boot/veneer/ppc/vrmp.s b/private/ntos/boot/veneer/ppc/vrmp.s
new file mode 100644
index 000000000..f47b798c2
--- /dev/null
+++ b/private/ntos/boot/veneer/ppc/vrmp.s
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1995 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrmp.s $
+ * $Revision: 1.5 $
+ * $Date: 1996/06/20 16:30:16 $
+ * $Locker: $
+ */
+
+#include "VrBAT.h"
+
+/*
+ * The PPC Open Firmware implementation uses a different protocol
+ * for MP startup than the ARC specification. In this module,
+ * we implement the ARC startup protocol.
+ *
+ * The PPC OF binding specifies that the /cpus node has
+ * a method cpu-machine-execute ( addr cpu# -- true | false )
+ * where cpu# is the cpu number and addr is the address
+ * (in the parent's address space?) at which the cpu is to
+ * begin execution.
+ *
+ * The ARC specifies that a cpu is to spin on the state of the
+ * ProcessorStart bit in the BootStatus word of the cpu's Restart Block.
+ * When ProcessorStart = 1, the cpu switches context to that saved in
+ * the SaveArea array in the Restart Block.
+ *
+ * Define here the context switch routine and the polling loop.
+ */
+ .data
+ .align 4
+ .globl naperr
+naperr:
+ .ascii "processor not sleeping"
+
+ .text
+ .align 4
+ .globl ..fatal
+
+/*
+ * VOID ArcPoll(VOID)
+ */
+ .globl ArcPoll
+ArcPoll:
+ /*
+ * We have to figure out where our BootStatus and SaveArea are.
+ * There's no way to explicitly pass variables to this routine,
+ * so our caller has helpfully stuffed them into locations
+ * ArcPoll-8 and ArcPoll-4. Retrieve them into r3 and r4.
+ * The pvr is initialized in ArcPoll-12. This is used by
+ * the IdleCPU() to check whether the machine is Multi processor
+ * worthy or not. The pvr should match for all proceesors and
+ * rev > 3.4 to be MP worthy
+ * Incidentally, we can trash all our registers as we won't
+ * ever return from this loop and this routine is not TOC-based.
+ */
+
+ bl here
+here:
+ mfpvr r5
+ mflr r1 // r1 = here
+ mr r4, r1
+ stw r5, -16(r1) // store it before moving 0x1234
+ li r2, 0x1234
+ lwz r3, -12(r1)
+ stw r2, -12(r1)
+ mr r29, r1 // save off r1 for future use
+ lwz r1, -8(r1)
+
+cputest:
+ lwz r5, -12(r29)
+ cmplw r5, r2 // is still 1234
+ beq cputest
+ li r2, 0xBAD
+ cmplw r5, r2 // is it bad to start this cpu
+ bne gonow
+napnow: // put it to sleep
+ mfmsr r5
+ li r2, 4
+ rlwinm r2,r2,16,0,31
+ or r5,r5,r2
+ mtmsr r5
+// lis r3, (naperr>>16)
+// ori r3, r3, napper
+ b ..fatal
+
+gonow:
+ //
+ // Turn off data/address translation ( I.E. go to real mode )
+ //
+ bl RealMode
+
+ /*
+ * Spin on the ProcessorStart bit (bit 23 in PPC nomenclature).
+ */
+ArcSpin:
+ lwz r2, 0(r3)
+ extrwi. r2, r2, 1, 23
+ beq ArcSpin
+
+ /*
+ * ProcessorStart is 1: reload processor state.
+ */
+ li r2, 0x789a
+ stw r2, -12(r4)
+
+ lwz r2, 0x104(r1) // CR0-7
+ mtcrf 255, r2
+ lwz r2, 0x108(r1) // XER
+ mtxer r2
+ lwz r2, 0x110(r1) // IAR
+ lis r3, 0x8000
+ andc r2, r2, r3
+ mtlr r2
+
+ lwz r0, 0x84(r1)
+ // Get r1 later.
+ lwz r2, 0x8c(r1)
+ lwz r3, 0x90(r1)
+ lwz r4, 0x94(r1)
+ lwz r5, 0x98(r1)
+ lwz r6, 0x9c(r1)
+ lwz r7, 0xa0(r1)
+ lwz r8, 0xa4(r1)
+ lwz r9, 0xa8(r1)
+ lwz r10, 0xac(r1)
+ lwz r11, 0xb0(r1)
+ lwz r12, 0xb4(r1)
+ lwz r13, 0xb8(r1)
+ lwz r14, 0xbc(r1)
+ lwz r15, 0xc0(r1)
+ lwz r16, 0xc4(r1)
+ lwz r17, 0xc8(r1)
+ lwz r18, 0xcc(r1)
+ lwz r19, 0xd0(r1)
+ lwz r20, 0xd4(r1)
+ lwz r21, 0xd8(r1)
+ lwz r22, 0xdc(r1)
+ lwz r23, 0xe0(r1)
+ lwz r24, 0xe4(r1)
+ lwz r25, 0xe8(r1)
+ lwz r26, 0xec(r1)
+ lwz r27, 0xf0(r1)
+ lwz r28, 0xf4(r1)
+ lwz r29, 0xf8(r1)
+ lwz r30, 0xfc(r1)
+ lwz r31,0x100(r1)
+
+ lwz r1, 0x88(r1)
+ blr
+
+
+/*
+ * Goto real mode via a branch and link to this routine. We'll turn off
+ * data and instruction address translation and reset the program counter
+ * so the return from this routine leaves the cpu in real mode.
+ */
+ .globl RealMode
+RealMode:
+ mflr r20
+ mfmsr r21 // get current state
+ rlwinm r21, r21, 0, ~EXTRNL_INT_ENABL // clear interrupt enable
+ mtmsr r21 // disable interrupts
+ rlwinm r21, r21, 0, ~(DATA_ADDR_XLATE | INSTR_ADDR_XLATE )
+ mtsrr1 r21 // desired initial state
+ rlwinm r20, r20, 0, 0x7fffffff // physical return addrress
+ mtsrr0 r20
+ rfi // return
+
+ .globl EndArcPoll
+EndArcPoll:
diff --git a/private/ntos/boot/veneer/ppc/vrstart.s b/private/ntos/boot/veneer/ppc/vrstart.s
new file mode 100644
index 000000000..5a934a1af
--- /dev/null
+++ b/private/ntos/boot/veneer/ppc/vrstart.s
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1994 FirePower Systems Inc.
+ *
+ * $RCSfile: vrstart.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/06/20 16:30:20 $
+ * $Locker: $
+ */
+
+ .text
+ .align 4
+
+ .globl start
+start:
+
+ /*
+ * We get control from the firmware here.
+ * As of 4/19/94, we're getting the following arguments:
+ * r1 initial stack pointer
+ * r2 zero (we must set up TOC)
+ * r3 reserved (residual data)
+ * r4 client program entry point
+ * r5 client interface handler
+ * r6 client program argument address
+ * r7 client program argument length
+ *
+ * Note that we're receiving all our arguments in registers;
+ * if we call C subroutines before calling main we'll
+ * have to save state...so it might not be best to use bzero()
+ * (unless we recode it in assembler).
+ */
+
+ /*
+ * XXX - We may need to remap ourselves. If so, that code goes here.
+ * XXX - Is bss zeroed? If not, do that here.
+ */
+
+ /*
+ * Set up the veneer's TOC pointer.
+ */
+
+ bl skip_toc
+ .word .toc
+skip_toc:
+ mflr r2
+ lwz r2, 0(r2)
+
+ /*
+ * Now we know where we are. Store the cif_handler, find main,
+ * and jump to it.
+ */
+ lwz r8, [toc]CifHandler(rtoc)
+ stw r5, 0(r8)
+
+ .extern main
+ lwz r8, [toc]main(rtoc)
+ lwz r8, 0(r8)
+ mtspr ctr, r8
+ bctrl // call main()
+
+ /*
+ * We should never get back here.
+ */
+ li r3, 0
+ .extern OFExit
+ lwz r8, [toc]OFExit(rtoc)
+ lwz r8, 0(r8)
+ mtspr ctr, r8
+ bctrl // call OFExit()
+
+ /*
+ * We should NEVER get here.
+ */
+ li r0, 0
+ mtlr r0
+ blr
+
+
+
+ .globl ..VrGetProcRev
+..VrGetProcRev:
+ mfpvr r.3 // get processor version
+ blr
+..VrGetProcRev.end:
+
+
+
+ .globl ..call_firmware
+..call_firmware:
+ lwz r4, [toc]CifHandler(rtoc)
+ lwz r4, 0(r4)
+ mtspr ctr, r4
+ bctr
+
+ .globl ..get_toc
+..get_toc:
+ mr r3, r2
+ blr
+
+ .reldata
+ .align 2
+ .globl call_firmware
+call_firmware:
+ .long ..call_firmware,.toc
+ .globl get_toc
+get_toc:
+ .long ..get_toc,.toc
+
+ .data
+ .align 4
+CifHandler:
+ .long 0
+
+
diff --git a/private/ntos/boot/veneer/proto.h b/private/ntos/boot/veneer/proto.h
new file mode 100644
index 000000000..4685742bf
--- /dev/null
+++ b/private/ntos/boot/veneer/proto.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: proto.h $
+ * $Revision: 1.13 $
+ * $Date: 1996/06/17 02:55:59 $
+ * $Locker: $
+ *
+ */
+
+#define prl_t CM_PARTIAL_RESOURCE_LIST
+#define prd_t CM_PARTIAL_RESOURCE_DESCRIPTOR
+
+ // vrmain.c
+
+VOID VrMoveNode(PCONFIGURATION_NODE, PCONFIGURATION_NODE,
+ PCONFIGURATION_NODE, CONFIGURATION_CLASS, CONFIGURATION_TYPE);
+LONG claimreal(PVOID, ULONG);
+
+ // vrmemory.c
+
+PMEMORY_DESCRIPTOR
+VrGetMemoryDescriptor( PMEMORY_DESCRIPTOR MemoryDescriptor );
+VOID VrCreateMemoryDescriptors( VOID );
+VOID VrMemoryInitialize( VOID );
+VOID DisplayMemory(VOID);
+
+ // vrdisp.c
+
+PARC_DISPLAY_STATUS VrGetDisplayStatus( ULONG FileId );
+ARC_STATUS VrTestUnicodeCharacter( ULONG FileId, WCHAR UnicodeCharacter );
+VOID VrDisplayInitialize( VOID );
+
+ // vrconsole.c
+
+PCHAR VrFindConsolePath(char *console);
+
+ // vrlib.c
+
+#if defined(_M_PPC) && defined(_MSC_VER) && (_MSC_VER>=1000)
+#pragma function(strcmp)
+#pragma function(strlen)
+#pragma function(strcpy)
+#pragma function(strcat)
+#endif
+
+int get_bool_prop(phandle, char *);
+int decode_int(UCHAR *);
+int get_int_prop(phandle node, char *key);
+reg * decode_reg(UCHAR *buf, int buflen, int addr_cells, int size_cells);
+reg * get_reg_prop(phandle node, char *key, int index);
+char * get_str_prop(phandle node, char *key, allocflag alloc);
+int strcmp(const char *s, const char *t);
+int strncmp(const char *s, const char *t, size_t len);
+int strncasecmp(const char *s, const char *t, size_t len);
+size_t strlen(const char *s);
+char * strcpy(char *to, const char *from);
+char * strcat(char *to, const char *from);
+VOID bcopy(char *from, char *to, int len);
+VOID bzero(char *cp, int len);
+VOID * zalloc(int size);
+VOID sleep(ULONG delay);
+int claim(void *adr, int bytes);
+VOID * alloc(int size, int align);
+int atoi(char *s);
+char * index(char *s, int c);
+char * strcsep(char *s, const char sep);
+char * strctok(char *s, const char sep);
+char * capitalize(char *s);
+VOID warn(char *fmt, ...);
+VOID fatal(char *fmt, ... );
+VOID debug(int debug_level, char *fmt, ...);
+VOID sprintf(char *, char *, ...);
+VOID putchar(char c);
+VOID puts(char *s);
+VOID gets(char *inbuf);
+
+ // vrconfig.c
+
+PCONFIGURATION_COMPONENT VrAddChild( PCONFIGURATION_COMPONENT Component,
+ PCONFIGURATION_COMPONENT NewComponent, PVOID ConfigurationData );
+ARC_STATUS VrDeleteComponent( PCONFIGURATION_COMPONENT Component );
+PCONFIGURATION_COMPONENT VrGetChild (
+ PCONFIGURATION_COMPONENT Component );
+PCONFIGURATION_COMPONENT VrGetParent(PCONFIGURATION_COMPONENT Component);
+PCONFIGURATION_COMPONENT VrGetPeer(PCONFIGURATION_COMPONENT Component);
+PCONFIGURATION_COMPONENT VrGetComponent( PCHAR Path );
+ARC_STATUS VrGetConfigurationData ( PVOID ConfigurationData,
+ PCONFIGURATION_COMPONENT Component );
+ARC_STATUS VrSaveConfiguration( VOID );
+VOID VrConfigInitialize( VOID );
+
+ // vrio.c
+
+ARC_STATUS VrOpen( PCHAR OpenPath, OPEN_MODE OpenMode, PULONG FileId );
+ARC_STATUS VrClose( ULONG FileId );
+ARC_STATUS VrRead( ULONG FileId, PVOID Buffer, ULONG Length, PULONG Count );
+ARC_STATUS VrWrite( ULONG FileId, PVOID Buffer, ULONG Length, PULONG Count );
+ARC_STATUS VrMount( PCHAR MountPath, MOUNT_OPERATION Operation );
+ARC_STATUS VrSeek( ULONG FileId, PLARGE_INTEGER Offset, SEEK_MODE SeekMode );
+ARC_STATUS VrGetDirectoryEntry( ULONG FileId, PDIRECTORY_ENTRY Buffer,
+ ULONG Length, PULONG Count );
+ARC_STATUS VrGetFileInformation( ULONG FileId, PFILE_INFORMATION pFI );
+ARC_STATUS VrGetReadStatus( ULONG FileId );
+ARC_STATUS VrSetFileInformation( ULONG FileId, ULONG AttributeFlags,
+ ULONG AttributeMask );
+VOID VrIoInitialize( VOID );
+
+
+ // vrcpiwrp.c
+
+phandle OFPeer(phandle device_id);
+phandle OFChild(phandle device_id);
+phandle OFParent(phandle device_id);
+long OFGetproplen( phandle device_id, char *name );
+long OFGetprop( phandle device_id, char *name, char *buf, ULONG buflen );
+long OFNextprop( phandle device_id, char *name, char *buf );
+long OFSetprop( phandle device_id, char *name, char *buf, ULONG buflen );
+phandle OFFinddevice( char *devicename);
+ihandle OFOpen( char *devicename);
+void OFClose(ihandle id);
+long OFRead( ihandle instance_id, PCHAR addr, ULONG len );
+long OFWrite( ihandle instance_id, PCHAR addr, ULONG len );
+long OFSeek( ihandle instance_id, ULONG poshi, ULONG poslo );
+ULONG OFClaim( PCHAR addr, ULONG size, ULONG align );
+VOID OFRelease( PCHAR addr, ULONG size );
+long OFPackageToPath( phandle device_id, char *addr, ULONG buflen );
+long OFInstanceToPath( ihandle ih, char *addr, ULONG buflen );
+phandle OFInstanceToPackage(ihandle ih);
+long OFCallMethod( ULONG n_outs, ULONG n_ins, ULONG *outp, char *method,
+ ihandle id, ... );
+long OFInterpret( ULONG n_outs, ULONG n_ins, ULONG *outp, char *cmd, ... );
+ULONG OFMilliseconds( VOID );
+VOID OFBoot( char *bootspec );
+VOID OFEnter( VOID );
+VOID OFExit( VOID );
+
+ // vrtree.c
+
+void walk_obp( phandle node, CONFIGURATION_NODE *here,
+ CONFIGURATION_NODE *parent, CONFIGURATION_NODE *peer);
+
+ // vrtrunk.c
+VOID vr_dump_config_node(PCONFIGURATION_NODE);
+prl_t * grow_prl(PCONFIGURATION_NODE node, int dev_specific);
+CONFIGURATION_NODE *add_new_child(
+ CONFIGURATION_NODE *, char *, CONFIGURATION_CLASS, CONFIGURATION_TYPE);
+
+ // vrload.c
+
+VOID VrCopyArguments( ULONG Argc, PCHAR Argv[] );
+ARC_STATUS VrGenerateDescriptor( PMEMORY_DESCRIPTOR MemoryDescriptor,
+ MEMORY_TYPE MemoryType, ULONG BasePage, ULONG PageCount );
+ARC_STATUS VrLoad( PCHAR ImagePath, ULONG TopAddress, PULONG EntryAddress,
+ PULONG LowAddress );
+ARC_STATUS VrInvoke( ULONG EntryAddress, ULONG StackAddress, ULONG Argc,
+ PCHAR Argv[], PCHAR Envp[] );
+ARC_STATUS VrExecute( PCHAR ImagePath, ULONG Argc, PCHAR Argv[], PCHAR Envp[] );
+VOID VrLoadInitialize( VOID );
+
+ // vrmalloc.c
+
+char * malloc(unsigned);
+void free(char *);
+int log2(int);
+
+
+ // vrdumptr.c
+
+VOID quick_dump_tree(PCONFIGURATION_NODE node);
+VOID dump_tree(PCONFIGURATION_NODE node);
+VOID DisplayConfig(PCONFIGURATION_COMPONENT);
+
+
+ // vrmisc.c
+
+PTIME_FIELDS VrGetTime( VOID );
+ULONG VrGetRelativeTime( VOID );
+VOID VrFlushAllCaches( VOID );
+VOID VrTimeInitialize( VOID );
+
+ // vrrstart.c
+
+VOID VrEnterInteractiveMode( VOID );
+PSYSTEM_ID VrGetSystemId( VOID );
+VOID VrPowerDown( VOID );
+VOID VrReboot( VOID );
+VOID VrRestart( VOID );
+VOID VrHalt( VOID );
+VOID VrRestartInitialize( VOID );
+
+ // vrsup.c
+
+PCONFIGURATION_NODE ArcPathToNode(PCHAR Path);
+PCHAR NodeToArcPath(PCONFIGURATION_NODE node);
+PCONFIGURATION_NODE PackageToNode(phandle ph);
+PCONFIGURATION_NODE PathToNode(PCHAR path);
+PCONFIGURATION_NODE InstanceToNode(ihandle ih);
+phandle NodeToPackage(PCONFIGURATION_NODE node);
+PCHAR NodeToPath(PCONFIGURATION_NODE node);
+ihandle NodeToInstance(PCONFIGURATION_NODE node);
+phandle FindNodeByType(char *);
+ihandle OpenPackage( phandle );
+
+ // vrenv.c
+
+PCHAR VrGetEnvironmentVariable( PCHAR Variable );
+ARC_STATUS VrSetEnvironmentVariable( PCHAR Variable, PCHAR Value );
+VOID VrEnvInitialize( VOID );
+
+ // vrpehdr.c
+
+void *load_file(ihandle bootih);
+
+ // vrstart.s
+
+int call_firmware(ULONG *);
+
+ // pxcache.s
+
+VOID PSIFlushCache(VOID);
+VOID PPCFlushAllCaches(VOID);
diff --git a/private/ntos/boot/veneer/sources b/private/ntos/boot/veneer/sources
new file mode 100644
index 000000000..9280ea3cb
--- /dev/null
+++ b/private/ntos/boot/veneer/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1995 Motorola Corporation
+Copyright (c) 1995 FirePower Systems, Inc.
+
+Module Name:
+
+ Veneer sources.
+
+Abstract:
+
+
+Author:
+
+ $RCSfile: sources $
+ $Revision: 1.5 $
+ $Date: 1996/03/01 20:17:49 $
+ $Locker: $
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=bldr
+
+TARGETNAME=veneer
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+VENEER_VERSION=0x0
+VENEER_REVISION=0x9909
+
+C_DEFINES=$(C_DEFINES) -D_NTSYSTEM_ -Dppc=1 -D$(CPU)=1 -D_$(CPU)_=1 -DVENEER_VERSION=$(VENEER_VERSION) -DVENEER_REVISION=$(VENEER_REVISION)
+
+# INCLUDES=..\..\inc
+INCLUDES=$(BASEDIR)\private\ntos\inc
+
+!IFDEF DDKBUILDENV
+INCLUDES=$(BASEDIR)\SRC\HAL\INC
+!ENDIF
+
+CFLAGS= /W3 /Oxs /Zd -ZB64
+
+!IF DEFINED (BUILTBY)
+C_DEFINES=$(C_DEFINES) -DBUILTBY=$(BUILTBY)
+!ENDIF
+
+SOURCES=
+
diff --git a/private/ntos/boot/veneer/veneer.h b/private/ntos/boot/veneer/veneer.h
new file mode 100644
index 000000000..aae1b1d1c
--- /dev/null
+++ b/private/ntos/boot/veneer/veneer.h
@@ -0,0 +1,287 @@
+/*++
+ *
+ * Copyright (c) 1994,1996 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: veneer.h $
+ * $Revision: 1.20 $
+ * $Date: 1996/06/19 23:13:15 $
+ * $Locker: $
+ *
+ *
+
+
+Module Name:
+
+ veneer.h
+
+Abstract:
+
+ This module contains the private data structures and procedure
+ prototypes for the veneer for the PowerPC NT.
+
+ This module is specifically tailored for the PowerPro and PowerTop
+ systems.
+
+Author:
+
+ A. Benjamin 9-May-1994
+
+Revision History:
+ 20-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ Added VRDBG_LOAD.
+ 13-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ Added ReadAheadCount and ReadAheadBuffer[2] in FileTable.
+ 12-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ Added Delete and NetworkDevice flags in FILE_FLAGS.
+
+
+--*/
+
+
+#ifndef _VENEER
+#define _VENEER
+
+//----------------------------------------------------------------
+//
+// Headers
+//
+
+#include <windef.h>
+#include "vrheader.h"
+#include <arc.h>
+#include <arccodes.h>
+#include <stdarg.h>
+
+#ifdef putchar
+# undef putchar
+#endif
+#ifdef puts
+# undef puts
+#endif
+
+//----------------------------------------------------------------
+//
+// Define common macros....
+//
+
+//----------------------------------------------------------------
+//
+// IEEE 1275-1994 definitions
+//
+
+typedef long phandle;
+typedef long ihandle;
+
+typedef struct {
+ long hi, lo;
+ long size;
+} reg;
+
+//----------------------------------------------------------------
+//
+// Global definitions and macros
+//
+
+#define MAX_IDE_DEVICE 4
+
+#ifdef BAT_MMU
+#define CLAIM(BaseAddr, SizeOfImage) \
+ claim(BaseAddr, SizeOfImage)
+#else
+#define CLAIM(BaseAddr, SizeOfImage) \
+ claimreal(BaseAddr, SizeOfImage)
+#endif
+
+
+typedef enum {
+ NOALLOC,
+ ALLOC
+} allocflag;
+
+#define new(t) (t *)zalloc(sizeof(t));
+
+#ifdef islower
+# undef islower
+#endif
+#define islower(c) (((c) >= 'a') && ((c) <= 'z'))
+
+#ifdef toupper
+# undef toupper
+#endif
+#define toupper(c) (((c) - 'a') + 'A')
+
+//
+// Current version and revision numbers.
+// These values are in OSLoader specifications (3-49).
+//
+#define ARC_VERSION 2
+#define ARC_REVISION 0
+
+//
+// CPU type
+//
+
+typedef enum {
+ PPC_UNKNOWN = 0,
+ PPC_601 = 1,
+ PPC_603 = 3,
+ PPC_604 = 4,
+ PPC_603E = 6,
+ PPC_604E = 9,
+ nPROCESSOR_TYPE
+} PROCESSOR_TYPE;
+
+
+//
+// Definitions associated with ARC.
+//
+#define SYSTEM_BLOCK_SIGNATURE 0x53435241
+#define RSTB_SIGNATURE 0x42545352
+
+//
+// The current (1/95) PowerPC port requires a "MIPS kseg0"-like
+// mapping which aliases 0x80000000 to 0x00000000. This macro,
+// used by claim(), undoes the mapping.
+//
+#define MAP(x) ((ULONG)(x) & ~0x80000000)
+#define UNMAP(x) ((ULONG)(x) | 0x80000000)
+
+
+//----------------------------------------------------------------
+//
+// Veneer data structures and declarations
+//
+
+/*
+ * This data structure is intended to link the components of the ARC
+ * tree with the nodes of the OF tree.
+ */
+typedef struct _CONFIGURATION_NODE {
+ phandle OfPhandle;
+ CONFIGURATION_COMPONENT Component;
+ CM_PARTIAL_RESOURCE_LIST *ConfigurationData;
+ struct _CONFIGURATION_NODE *Peer, *Child, *Parent;
+ char *ComponentName;
+ int Wildcard;
+ char *WildcardAddrPath;
+} CONFIGURATION_NODE, *PCONFIGURATION_NODE;
+
+
+//
+// Define the vendor specific entry point numbers.
+//
+typedef enum _VENDOR_ENTRY {
+ MaximumVendorRoutine
+ } VENDOR_ENTRY;
+
+//
+// Define file table structure.
+//
+#define FILE_TABLE_SIZE 32
+
+typedef struct _FILE_FLAGS {
+ ULONG Open : 1;
+ ULONG Read : 1;
+ ULONG Write : 1;
+ ULONG Delete : 1;
+ ULONG Device : 1;
+ ULONG Partition : 1;
+ ULONG DisplayDevice : 1;
+ ULONG RemovableDevice : 1;
+ ULONG NetworkDevice : 1;
+} FILE_FLAGS, *PFILE_FLAGS;
+
+#define MAX_PATH_NAME_SIZE 128
+
+typedef struct _FILE_TABLE_ENTRY {
+ ihandle IHandle;
+ FILE_FLAGS Flags;
+ LARGE_INTEGER Position;
+ PCHAR PathName;
+ LONG ReadAheadCount;
+ CHAR ReadAheadBuffer[2];
+} FILE_TABLE_ENTRY, *PFILE_TABLE_ENTRY;
+extern FILE_TABLE_ENTRY FileTable[];
+
+//
+// Define the keyboard and mouse id strings.
+//
+#define KBD_IDENTIFIER "PCAT_ENHANCED"
+#define MOUSE_IDENTIFIER "PS2 MOUSE"
+
+
+//----------------------------------------------------------------
+//
+// External/Global variable declarations
+//
+
+extern int VrDebug;
+extern CONFIGURATION_NODE *RootNode;
+extern ihandle ConsoleIn, ConsoleOut;
+extern BOOLEAN use_bat_mapping;
+
+//----------------------------------------------------------------
+//
+// Function prototypes
+//
+
+//
+// Useful macros for pragma message, ie. #pragma message(REVIEW "some text")
+//
+#define QUOTE(x) #x
+#define IQUOTE(x) QUOTE(x)
+#define REVIEW __FILE__ "(" IQUOTE(__LINE__) ") : REVIEW -> "
+
+//----------------------------------------------------------------
+//
+// Debugging definitions and macros
+//
+
+#define STATIC static
+
+#define VRDBG_VR 0x00000001 // printout "ARC" interface activity.
+#define VRDBG_OF 0x00000002
+#define VRDBG_TEST 0x00000004
+#define VRDBG_TREE 0x00000008
+#define VRDBG_MEM 0x00000010
+#define VRDBG_MAIN 0x00000020
+#define VRDBG_ENTRY 0x00000040
+#define VRDBG_PE 0x00000080
+#define VRDBG_CONF 0x00000100
+#define VRDBG_OPEN 0x00000200
+#define VRDBG_CONFIG 0x00000400
+#define VRDBG_LOAD 0x00000800
+#define VRDBG_RDWR 0x00001000
+#define VRDBG_ARGV 0x00002000
+#define VRDBG_ENV 0x00004000 // printout environment values and variables
+#define VRDBG_DUMP 0x00008000
+#define VRDBG_HOLDIT 0x00010000
+#define SANDALFOOT 0x00020000
+//#define CDROMHACK 0x00040000
+#define VRDBG_TMP 0x00080000
+#define VRDBG_ARCDATA 0x00100000
+#define VRDBG_SCSI 0x00200000 // print out scsi node activity
+#define VRDBG_IDE 0x00400000 // print out ide node activity
+#define VRDBG_TIME 0x00800000
+#define VRDBG_ALL 0xffffffff
+
+#define VRASSERT(_exp) \
+ if (!(_exp)) { \
+ warn("Assertion Failure: line %d, File %s\n",\
+ __LINE__, __FILE__); \
+ warn("Veneer Assertion Failure:" #_exp "\n"); \
+ ArcHalt();\
+ }
+
+#define DBGSET(_value) ((_value)&(VrDebug))
+#define VRDBG(_value, _str) \
+ { \
+ if (DBGSET(_value)) { \
+ _str; \
+ } \
+ }
+
+#include "proto.h"
+
+#endif // _VENEER
diff --git a/private/ntos/boot/veneer/verno.c b/private/ntos/boot/veneer/verno.c
new file mode 100644
index 000000000..0ed3e5fd8
--- /dev/null
+++ b/private/ntos/boot/veneer/verno.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1995,1996 FirePower Systems, Inc.
+ *
+ * $RCSfile: verno.c $
+ * $Revision: 1.15 $
+ * $Date: 1996/06/08 00:59:34 $
+ * $Locker: $
+ */
+
+#include "veneer.h"
+
+#define VENEER_MAJOR 3
+#define VENEER_MINOR 00
+#define __BLDSTAMP__ __DATE__ " - " __TIME__
+
+#define SALUTATION "Open Firmware ARC Interface Version %d.%d (%s)\n"
+#define VERSION "FirmWorks,ENG,%d.%d,%s,%s,GENERAL"
+
+
+void
+Salutation(void)
+{
+ warn(SALUTATION, VENEER_MAJOR, VENEER_MINOR, __BLDSTAMP__);
+}
+
+
+char *
+VeneerVersion(void)
+{
+ static char buf[128];
+
+ sprintf(buf, VERSION, VENEER_MAJOR, VENEER_MINOR, __DATE__, __TIME__);
+ return (buf);
+}
diff --git a/private/ntos/boot/veneer/vrbat.h b/private/ntos/boot/veneer/vrbat.h
new file mode 100644
index 000000000..696a7dede
--- /dev/null
+++ b/private/ntos/boot/veneer/vrbat.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1995 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1996 FirePower, Inc.
+ *
+ * $RCSfile: vrbat.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/16 18:05:24 $
+ * $Locker: $
+ */
+
+#ifndef VRBAT_H
+#define VRBAT_H
+
+/*
+ ***********************************************************************
+ *
+ * MSR bit definitions
+ *
+ ***********************************************************************
+ */
+#define INSTR_ADDR_XLATE 0x00000020 // Instruction Addr xlate
+#define DATA_ADDR_XLATE 0x00000010 // Data Addr xlate
+#define EXTRNL_INT_ENABL 0x00008000 // EE bit
+#define PRIVILEDGES 0x00004000 // PR bit for supervisor/user
+ // mode. Setting this bit to 1
+ // restricts access to user only
+#define XCPT_LE_MODE 0x00010000 // take exceptions in little
+ // endian mode.
+#define LITTLE_ENDIAN 0x00000001 // run little endian mode
+#define MCHNE_CHK_EN 0x00001000 // Machine Check Enable
+#define FLOAT_PNT_EN 0x00002000
+
+/*
+************************************************************************
+**
+** Block Address Translation registers
+**
+************************************************************************
+*/
+//
+// Here are defines for the UPPER 32 bit bat register:
+//
+#define PAGE_INDEX_BITS 0xfffe0000
+#define BEPI(x) ( x & PAGE_INDEX_BITS )
+
+#define A_128K_BLOCK_SIZE 0x00000000
+#define A_256K_BLOCK_SIZE 0x00000004
+#define A_512K_BLOCK_SIZE 0x0000000c
+#define A_1MEG_BLOCK_SIZE 0x0000001c
+#define A_2MEG_BLOCK_SIZE 0x0000003c
+#define A_4MEG_BLOCK_SIZE 0x0000007c
+#define AN_8MEG_BLOCK_SIZE 0x000000fc
+#define A_16MB_BLOCK_SIZE 0x000001fc
+#define A_32MB_BLOCK_SIZE 0x000003fc
+#define A_64MB_BLOCK_SIZE 0x000007fc
+#define A_128M_BLOCK_SIZE 0x00000ffc
+#define A_256M_BLOCK_SIZE 0x00001ffc
+
+#define SUPERVISOR_ONLY 0x00000002
+#define USER_ACCESS 0x00000001
+
+//
+// The Lower BAT Register
+//
+#define BRPN(x) ( (x >> 8) & PAGE_INDEX_BITS)
+
+//
+// WIMG: VIMVENDERS BITS:
+//
+#define WRITE_THROUGH 0x00000040
+#define CACHE_INHIBIT 0x00000020
+#define MEMORY_COHRNCY 0x00000010
+#define GUARDED_BLOCK 0x00000008 // for IBAT use only....
+
+#define PAGE_RW_ACCESS 0x00000002
+#define PAGE_RO_ACCESS 0x00000001
+#define PAGE_UNAVAILBL 0x00000000
+
+
+//
+// define the special purpose register values for
+// use with the "mfspr, mtspr" instructions
+//
+#define SDR1 25
+#define IBAT0_UPPER 528
+#define IBAT0_LOWER 529
+#define IBAT1_UPPER 530
+#define IBAT1_LOWER 531
+#define IBAT2_UPPER 532
+#define IBAT2_LOWER 533
+#define IBAT3_UPPER 534
+#define IBAT3_LOWER 535
+
+#define DBAT0_UPPER 536
+#define DBAT0_LOWER 537
+#define DBAT1_UPPER 538
+#define DBAT1_LOWER 539
+#define DBAT2_UPPER 540
+#define DBAT2_LOWER 541
+#define DBAT3_UPPER 542
+#define DBAT3_LOWER 543
+
+//
+// data which written to the BAT's upper register
+// will turn off it's translation abilities
+//
+#define INVALIDATE 0x00000000
+#define KSEG0 0x80000000
+#define LDW(x,y) addi x, 0, (y&0xffff) ;\
+ addis x, 0, (y>>16)
+
+#endif //VRBAT_H
diff --git a/private/ntos/boot/veneer/vrconfig.c b/private/ntos/boot/veneer/vrconfig.c
new file mode 100644
index 000000000..e09fcd2c4
--- /dev/null
+++ b/private/ntos/boot/veneer/vrconfig.c
@@ -0,0 +1,567 @@
+/*++
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrconfig.c $
+ * $Revision: 1.10 $
+ * $Date: 1996/04/15 02:56:07 $
+ * $Locker: $
+ *
+
+
+Module Name:
+
+ vrconfig.c
+
+Abstract:
+
+ This module contains the configuration functions.
+
+Author:
+
+ A. Benjamin 2-May-1994
+
+Revision History:
+09-06-94 Shin Iwamoto at FirePower Systems Inc.
+ Added checking ConfigurationData in VrGetConfigurationData().
+ Added checking Componet in VrGetParent() and VrGetPeer().
+09-01-94 Shin Iwamoto at FirePower Systems Inc.
+ Added to be an error if the ConfigurationDataLength field of
+ NewComponent is non-zero and the COnfigurationData parameter is null.
+07-22-94 Shin Iwamoto at FirePower Systems Inc.
+ Added VrAddChild() and VrDeleteComponent().
+07-21-94 Shin Iwamoto at FirePower Systems Inc.
+ Moved the intialization of vector table for VrGetEnvironmentVariable
+ and VrGetMemoryDescriptor into vrenv.c.
+07-20-94 Shin Iwamoto at FirePower Systems Inc.
+ Moved VrSystemInit() and VrNotYet() to vrmain.c and then
+ renamed VrSystemInit() with VrConfigInitialize() for only
+ initializing the vector table.
+
+--*/
+
+
+#include "veneer.h"
+
+
+/*
+ * Name: VrAddChild
+ *
+ * Description:
+ * This function adds a new component entry as a child of Component,
+ * including an identifier string if the IdentifierLength field of
+ * NewComponent is non-zero, and configuration data if the
+ * ConfigurationDataLength field of NewComponent is non-zero and the
+ * ConfigurationData parameter is present. If Componet is NULL,
+ * the root component is being added.
+ *
+ * Arguments:
+ * Component - Supplies a pointer to a configuration component.
+ * NewComponent- Supplies a pointer to a new configuration component
+ * to be added as a child of Component.
+ * ConfigurationData - Supplies an optional pointer to a configuration
+ * data buffer.
+ *
+ * Return Value:
+ * Returns a pointer to the new configuration component entry.
+ * If the create operation was unsuccessful, NULL is returned.
+ *
+ */
+PCONFIGURATION_COMPONENT
+VrAddChild(
+ IN PCONFIGURATION_COMPONENT Component,
+ IN PCONFIGURATION_COMPONENT NewComponent,
+ IN PVOID ConfigurationData OPTIONAL
+ )
+{
+ PCONFIGURATION_NODE ConfNode;
+ PCONFIGURATION_NODE ChildNode;
+ PCONFIGURATION_NODE ParentNode;
+
+ //
+ // If there is not enough space for the new component, retrun NULL.
+ //
+ ConfNode = new(CONFIGURATION_NODE);
+ if ((PCHAR) ConfNode == NULL) {
+ return (PCONFIGURATION_COMPONENT) NULL;
+ }
+
+ //
+ // Fill in new configuration entry with Identifier and ConfigurationData.
+ //
+ bcopy((PCHAR)NewComponent, (PCHAR)&ConfNode->Component,
+ sizeof(CONFIGURATION_COMPONENT));
+ if (NewComponent->IdentifierLength != 0) {
+ ConfNode->Component.Identifier = malloc(NewComponent->IdentifierLength);
+ if (ConfNode->Component.Identifier == NULL) {
+ ConfNode->Component.IdentifierLength = 0;
+ goto ErrorAddChild;
+ }
+ bcopy(NewComponent->Identifier, ConfNode->Component.Identifier,
+ NewComponent->IdentifierLength);
+ } else {
+ ConfNode->Component.Identifier = NULL; // For safety
+ }
+
+ if (NewComponent->ConfigurationDataLength != 0) {
+ if (ConfigurationData == NULL) {
+ ConfNode->Component.ConfigurationDataLength = 0;
+ goto ErrorAddChild;
+ }
+ ConfNode->ConfigurationData =
+ (CM_PARTIAL_RESOURCE_LIST *)
+ malloc(NewComponent->ConfigurationDataLength);
+
+ if (ConfNode->ConfigurationData == NULL) {
+ ConfNode->Component.ConfigurationDataLength = 0;
+ goto ErrorAddChild;
+ }
+ bcopy(ConfigurationData, (PCHAR)(ConfNode->ConfigurationData),
+ NewComponent->ConfigurationDataLength);
+ }
+
+ //
+ // If Component is NULL and the new Class is system, the root component
+ // is being added, otherwise the new is added according to Component.
+ //
+ if ((Component == NULL) && (NewComponent->Class == SystemClass)) {
+
+ //
+ // If the root component is being added, replace the root component.
+ // However, some information such as phandle are adhered.
+ // XXXX Is it Ok?
+ //
+ ConfNode->Peer = RootNode->Peer;
+ ConfNode->Child = RootNode->Child;
+ ConfNode->Parent = NULL;
+ ConfNode->OfPhandle = RootNode->OfPhandle;
+ RootNode = ConfNode;
+
+ //
+ // The parent of the old parent's children is changed.
+ //
+ ChildNode = ConfNode->Child;
+ while(ChildNode != NULL) {
+ ChildNode->Parent = ConfNode;
+ ChildNode = ChildNode->Peer;
+ }
+
+ } else {
+ if (Component == NULL) {
+ ParentNode = RootNode;
+ } else {
+ ParentNode = CONTAINING_RECORD(Component,
+ CONFIGURATION_NODE,
+ Component);
+ }
+ ConfNode->Peer = ParentNode->Child;
+ ParentNode->Child = ConfNode;
+ ConfNode->Child = NULL;
+ ConfNode->Parent = ParentNode;
+ ConfNode->OfPhandle = OFChild(ParentNode->OfPhandle);
+ if (!(ConfNode->OfPhandle)) { // This "can't happen."
+ goto ErrorAddChild;
+ }
+ }
+
+
+ return (&ConfNode->Component);
+
+
+ ErrorAddChild:
+ if (ConfNode->Component.IdentifierLength != 0) {
+ free(ConfNode->Component.Identifier);
+ }
+ if (ConfNode->Component.ConfigurationDataLength != 0) {
+ free((PVOID)ConfNode->ConfigurationData);
+ }
+ bzero((char *)ConfNode, sizeof(CONFIGURATION_NODE)); // For safety
+ free((char *) ConfNode);
+ return (PCONFIGURATION_COMPONENT) NULL;
+}
+
+
+/*
+ * Name: VrDeleteComponent
+ *
+ * Description:
+ * This function deletes a component entry. If the entry has one or more
+ * children, an error is returned, otherwise the entry is deleted.
+ * Deleting the entry will implicitly delete the identifier string and
+ * the configuration data.
+ *
+ * Arguments:
+ * Component - Supplies a pointer to a configuration component.
+ *
+ * Return Value:
+ * Returns ESUCCESS if the entry was successfully deleted, otherwise retunrs
+ * EINVAL or EACCES.
+ *
+ */
+ARC_STATUS
+VrDeleteComponent(
+ IN PCONFIGURATION_COMPONENT Component
+ )
+{
+ PCONFIGURATION_NODE ConfNode;
+ PCONFIGURATION_NODE SearchNode;
+
+ if (Component == NULL) {
+ return EINVAL;
+ }
+ if (!(Component->Version == ARC_VERSION &&
+ Component->Revision == ARC_REVISION)) {
+ return EINVAL;
+ }
+
+ ConfNode = CONTAINING_RECORD(Component,
+ CONFIGURATION_NODE,
+ Component);
+
+ //
+ // If Component's parent field is NULL, return EINVAL.
+ //
+ if (ConfNode->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If Component has children, return EACCES.
+ //
+ if (ConfNode->Child != NULL) {
+ return EACCES;
+ }
+
+ //
+ // Find the entry that points to Component, and point it to
+ // Components's peer. If this is Components's parent, update the child
+ // pointer, otherwise this is apeer and update the peer pointer.
+ //
+ SearchNode = ConfNode->Parent;
+ if (SearchNode->Child == ConfNode) {
+ SearchNode->Child = ConfNode->Peer;
+ } else {
+ SearchNode = SearchNode->Child;
+ while (SearchNode->Peer != ConfNode) {
+ SearchNode = SearchNode->Peer;
+ }
+ SearchNode->Peer = ConfNode->Peer;
+ }
+
+ //
+ // Free Conponent with Identifier and ConfigurationData, if any.
+ //
+ if (ConfNode->Component.IdentifierLength != 0) {
+ free(ConfNode->Component.Identifier);
+ }
+ if (ConfNode->Component.ConfigurationDataLength != 0) {
+ free((PVOID)ConfNode->ConfigurationData);
+ }
+ bzero((char *)ConfNode, sizeof(CONFIGURATION_NODE)); // For safety
+ free((char *) ConfNode);
+
+ return ESUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ The system configuration data structure is organized as a tree of
+ component structures. This function returns a pointer to the first
+ child of a configuration node.
+
+ If Component is null, then a pointer to the root node is returned.
+
+Arguments:
+
+ Component - pointer to a component structure.
+
+Return Value:
+
+ Returns a pointer to the structure of the child of component
+ if one exists, otherwise it returns a null pointer.
+
+--*/
+
+PCONFIGURATION_COMPONENT
+VrGetChild (
+ IN PCONFIGURATION_COMPONENT Component OPTIONAL
+ )
+{
+ PCONFIGURATION_NODE OfLink;
+
+ debug(VRDBG_VR, "VrGetChild: Entry - Component: %x\n", Component);
+
+ if (Component == (PCONFIGURATION_COMPONENT)NULL) {
+ debug(VRDBG_VR, "VrGetChild: Root %x\n", &RootNode->Component);
+ return &RootNode->Component;
+ }
+
+ OfLink = CONTAINING_RECORD(Component,
+ CONFIGURATION_NODE,
+ Component);
+
+ if (OfLink->Child == NULL ) {
+ debug(VRDBG_VR, "VrGetChild: NULL\n");
+ return NULL;
+ } else {
+ debug(VRDBG_VR, "VrGetChild: Child %x (%s)\n",
+ &OfLink->Child->Component, OfLink->Child->ComponentName);
+ return &OfLink->Child->Component;
+ }
+}
+
+PCONFIGURATION_COMPONENT
+VrGetParent(IN PCONFIGURATION_COMPONENT Component)
+{
+PCONFIGURATION_NODE OfLink;
+
+ debug(VRDBG_VR, "VrGetParent: Entry - Component: %x\n", Component);
+
+ if (Component == NULL) {
+ return NULL;
+ }
+ if (!(Component->Version == ARC_VERSION &&
+ Component->Revision == ARC_REVISION)) {
+ return NULL;
+ }
+
+ OfLink = CONTAINING_RECORD(Component,
+ CONFIGURATION_NODE,
+ Component);
+ if (OfLink->Parent == NULL) {
+ debug(VRDBG_VR, "VrGetParent: Exit-1\n");
+ return NULL;
+ } else {
+ debug(VRDBG_VR, "VrGetParent: Exit-2\n");
+ return &OfLink->Parent->Component;
+ }
+}
+
+PCONFIGURATION_COMPONENT
+VrGetPeer(IN PCONFIGURATION_COMPONENT Component)
+{
+ PCONFIGURATION_NODE OfNode;
+
+ debug(VRDBG_VR, "VrGetPeer: Entry - Component: %x\n", Component);
+
+ if (Component == NULL) {
+ return NULL;
+ }
+ if (!(Component->Version == ARC_VERSION &&
+ Component->Revision == ARC_REVISION)) {
+ return NULL;
+ }
+
+ OfNode = CONTAINING_RECORD(Component,
+ CONFIGURATION_NODE,
+ Component);
+ if (OfNode->Peer == NULL ) {
+ debug(VRDBG_VR, "VrGetPeer: NULL\n");
+ return NULL;
+ } else {
+ debug(VRDBG_VR, "VrGetPeer: Peer %x (%s)\n",
+ &OfNode->Peer->Component, OfNode->Peer->ComponentName);
+ return &OfNode->Peer->Component;
+ }
+}
+
+
+/*++
+ GetComponent - This function returns a pointer to the component structure
+ that best matches the path string pointed to by Path. The search algorithm
+ searches for each component starting with the first and continues
+ until either the string has been exhausted or no component mathes the
+ string.
+
+ BUBUG The spec. specifies the following two inconsistent return values
+
+ 1. The function returns a pointer to the last successfully matched
+ component.
+
+ 2. If the path is invalid or if a component structure does not
+ exist, this function returns a null pointer.
+--*/
+
+PCONFIGURATION_COMPONENT
+VrGetComponent(
+ IN PCHAR Path
+ )
+{
+ PCONFIGURATION_NODE Node;
+
+ debug(VRDBG_VR, "VrGetComponent: Entry - Path: %s\n", Path);
+
+ if (Node = ArcPathToNode(Path)) {
+ debug(VRDBG_VR, "VrGetComponent: Exit; found %x (%s)\n",
+ &Node->Component, Node->ComponentName);
+ return (&Node->Component);
+ } else {
+ debug(VRDBG_VR, "VrGetComponent: No match found!\n");
+ return (NULL);
+ }
+}
+
+
+/*++
+
+Routine Description:
+
+ This functions returns the configuration data associated with Component
+ in the buffer supplied by ConfigurationData. The length of the data
+ is stored in the Component structure.
+
+Arguments:
+
+ ConfigurationData - Supplies a pointer to a buffer to receive the
+ configuration data.
+
+ Component - Supplies a pointer to a configuration component.
+
+Return Value:
+
+ If the configuration data is successfully copied into the buffer
+ provided by ConfigurationData, ESUCCESS is returned. Otherwise one of
+ the following error codes is returned.
+
+ EINVAL Component is not a valid configuration component, or the
+ configuration is invalid.
+
+--*/
+
+ARC_STATUS
+VrGetConfigurationData (
+ OUT PVOID ConfigurationData,
+ IN PCONFIGURATION_COMPONENT Component
+ )
+{
+ PCONFIGURATION_NODE Node;
+ ULONG DataSize;
+
+ debug(VRDBG_VR, "VrGetConfigurationData: Entry - Config.Data: %x Comp.: %x\n",
+ ConfigurationData, Component);
+
+ if (Component == NULL) {
+ return EINVAL;
+ }
+ DataSize = Component->ConfigurationDataLength;
+
+ //
+ // check the passing parameters
+ //
+ if (DataSize == 0) {
+ return EINVAL;
+ }
+
+ Node = CONTAINING_RECORD( Component, CONFIGURATION_NODE, Component );
+
+#ifdef TOO_STRINGENT
+ //
+ // If Component's Parent field is NULL, return EINVAL.
+ //
+ if (Node->Parent == NULL) {
+ return EINVAL;
+ }
+
+ //
+ // If the Component doesn't point to a valid configuration component,
+ // return EINVAL.
+ //
+ if (!(Node->ConfigurationData->Version == ARC_VERSION &&
+ Node->ConfigurationData->Revision == ARC_REVISION)) {
+ return EINVAL;
+ }
+#endif
+
+ //
+ // Copy the data.
+ //
+
+ bcopy((PCHAR)Node->ConfigurationData, ConfigurationData, DataSize);
+
+ debug(VRDBG_VR, "VrGetConfigurationData: Exit; copied %d bytes from %x\n",
+ DataSize, Node->ConfigurationData);
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrSaveConfiguration
+ *
+ * Description:
+ * This function stores all of the configuration entries into NVRAM,
+ * including the associated identifier strings and configuration data.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * Returns ESUCCESS if thesave completed successfully, otherwise returns
+ * ENOSPC.
+ *
+ */
+ARC_STATUS
+VrSaveConfiguration(
+ VOID
+ )
+{
+ //
+ // Open Firmware doesn't batch the NVRAM writes; thus this always succeeds.
+ //
+ return ESUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine initializes the firmware vector in the system parameter
+ block.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+VrConfigInitialize(
+ VOID
+ )
+{
+ debug(VRDBG_ENTRY, "VrConfigInitialize BEGIN....\n");
+ (PARC_ADD_CHILD_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[AddChildRoutine] = VrAddChild;
+
+ (PARC_DELETE_COMPONENT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[DeleteComponentRoutine] =
+ VrDeleteComponent;
+ (PARC_GET_CHILD_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetChildRoutine] = VrGetChild;
+
+ (PARC_GET_PARENT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetParentRoutine] = VrGetParent;
+
+ (PARC_GET_PEER_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetPeerRoutine] = VrGetPeer;
+
+ (PARC_GET_DATA_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetDataRoutine] =
+ VrGetConfigurationData;
+ (PARC_GET_COMPONENT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetComponentRoutine] =
+ VrGetComponent;
+ (PARC_SAVE_CONFIGURATION_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[SaveConfigurationRoutine] =
+ VrSaveConfiguration;
+ debug(VRDBG_ENTRY, "VrConfigInitialize ....END\n");
+}
diff --git a/private/ntos/boot/veneer/vrcons.c b/private/ntos/boot/veneer/vrcons.c
new file mode 100644
index 000000000..e28a188f6
--- /dev/null
+++ b/private/ntos/boot/veneer/vrcons.c
@@ -0,0 +1,55 @@
+/*++
+
+ Copyright (c) 1995 FirePower Systems, Inc.
+
+ $RCSfile: vrcons.c $
+ $Revision: 1.6 $
+ $Date: 1996/02/17 00:34:54 $
+ $Locker: $
+
+Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+
+Module Name:
+
+ vrconsole.c
+
+--*/
+
+#include "veneer.h"
+
+ihandle ConsoleIn = 0, ConsoleOut = 0;
+
+/*
+ * Look up either the stdin or stdout and return an NT path to
+ * the device. The console argument should be either "stdin" or
+ * "stdout".
+ */
+
+PCHAR
+VrFindConsolePath(char *console)
+{
+ phandle chosen;
+ ihandle console_ih;
+ PCONFIGURATION_NODE node;
+
+ chosen = OFFinddevice("/chosen");
+ console_ih = get_int_prop(chosen, console);
+
+ if (console_ih == -1) {
+ return (NULL);
+ }
+
+ if (strcmp(console, "stdin") == 0) {
+ ConsoleIn = console_ih;
+ }
+ if (strcmp(console, "stdout") == 0) {
+ ConsoleOut = console_ih;
+ }
+
+ node = InstanceToNode(console_ih);
+ if (node == NULL) {
+ fatal("VrFindConsolePath: cannot locate %s node\n", console);
+ }
+
+ return (NodeToArcPath(node));
+}
diff --git a/private/ntos/boot/veneer/vrcpiwrp.c b/private/ntos/boot/veneer/vrcpiwrp.c
new file mode 100644
index 000000000..dfd9d0461
--- /dev/null
+++ b/private/ntos/boot/veneer/vrcpiwrp.c
@@ -0,0 +1,525 @@
+/*++
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrcpiwrp.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/02/26 20:17:32 $
+ * $Locker: $
+ *
+
+
+
+Module Name:
+
+ vrcpiwrp.c
+
+Abstract:
+
+ This module implements the wrapper for the P1275 boot firmware client
+ program interface. There is a wrapper routine for each of the client
+ interface service. The wrapper routine constructs a client interface
+ argument array as illustraed in the figure below, places its address
+ in r3 and transfers control to the client interface handler. The
+ return address of the wrapper routine is placed in lr register.
+
+ The Client interface handler performs the service specified in the
+ argument array and return to wrapper routine which in turn return
+ to the client program. The client interface handler places the return
+ value (success or failure) in %r3.
+
+
+ Layout of the argument array
+
+ +--------------------------------------+
+ | Name of the client interface service |
+ +--------------------------------------+
+ | Number of input arguments |
+ +--------------------------------------+
+ | Number of return values |
+ +--------------------------------------+
+ | Input arguments (arg1, ..., argN) |
+ +--------------------------------------+
+ | Returned values (ret1, ..., retN) |
+ +--------------------------------------+
+
+Author:
+
+ A. Benjamin 27-Apr-1994
+
+Revision History:
+07-20-94 Shin Iwamoto at FirePower Systems Inc.
+ Added OFBoot and OFEnter.
+
+
+--*/
+
+
+#include "veneer.h"
+
+#define VR_CIF_HANDLER_IN 3
+
+//
+// Device tree routines
+//
+
+//
+// Peer() - This routines outputs the identifier(phandle) of the device node that is
+// the next sibling of the specified device node.
+//
+// Inputs:
+// phandle - identifier of a device node
+//
+// Outputs:
+// sibling_phandle - identifier of the next sibling.
+// Zero if there are no more siblings.
+//
+
+//
+// peer
+//
+phandle
+OFPeer(phandle device_id)
+{
+ ULONG argarray[] = { (ULONG)"peer",1,1,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = device_id;
+ if (call_firmware(argarray) != 0) {
+ return (phandle)0;
+ }
+ return ((phandle)argarray[VR_CIF_HANDLER_IN+1]);
+}
+
+//
+//child
+//
+phandle
+OFChild(phandle device_id)
+{
+ ULONG argarray[] = { (ULONG)"child",1,1,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = device_id;
+ if (call_firmware(argarray) != 0) {
+ return (phandle)0;
+ }
+ return ((phandle)argarray[VR_CIF_HANDLER_IN+1]);
+}
+//
+// parent
+//
+phandle
+OFParent(phandle device_id)
+{
+ ULONG argarray[] = { (ULONG)"parent",1,1,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = device_id;
+ if (call_firmware(argarray) != 0) {
+ return (phandle)0;
+ }
+ return ((phandle)argarray[VR_CIF_HANDLER_IN+1]);
+}
+//
+//getproplen
+//
+long
+OFGetproplen(
+ phandle device_id,
+ char *name
+ )
+{
+ ULONG argarray[] = { (ULONG)"getproplen",2,1,0,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (long)device_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (long)name;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+2]);
+}
+//
+//getprop
+//
+long
+OFGetprop(
+ phandle device_id,
+ char *name,
+ char *buf,
+ ULONG buflen
+ )
+{
+ ULONG argarray[] = { (ULONG)"getprop",4,1,0,0,0,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (long)device_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (long)name;
+ argarray[VR_CIF_HANDLER_IN+2] = (long)buf;
+ argarray[VR_CIF_HANDLER_IN+3] = buflen;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+4]);
+}
+//
+//nextprop
+//
+long
+OFNextprop(
+ phandle device_id,
+ char *name,
+ char *buf
+ )
+{
+ ULONG argarray[] = { (ULONG)"nextprop",3,1,0,0,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (long)device_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (long)name;
+ argarray[VR_CIF_HANDLER_IN+2] = (long)buf;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+3]);
+}
+//
+//setprop
+//
+long
+OFSetprop(
+ phandle device_id,
+ char *name,
+ char *buf,
+ ULONG buflen
+ )
+{
+ ULONG argarray[] = { (ULONG)"setprop",4,1,0,0,0,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (long)device_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (long)name;
+ argarray[VR_CIF_HANDLER_IN+2] = (long)buf;
+ argarray[VR_CIF_HANDLER_IN+3] = buflen;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+4]);
+}
+
+//
+// finddevice
+//
+phandle
+OFFinddevice( char *devicename)
+{
+ ULONG argarray[] = { (ULONG)"finddevice",1,1,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (long)devicename;
+ if (call_firmware(argarray) != 0) {
+ return (phandle)0;
+ }
+ return ((phandle) argarray[VR_CIF_HANDLER_IN+1]);
+}
+
+//
+// open
+//
+ihandle
+OFOpen( char *devicename)
+{
+ ULONG argarray[] = { (ULONG)"open",1,1,0,0};
+
+ debug(VRDBG_OF, "OFOpen('%s')\n", devicename);
+ argarray[VR_CIF_HANDLER_IN+0] = (long)devicename;
+ if (call_firmware(argarray) != 0) {
+ return (ihandle)0;
+ }
+ return ((ihandle) argarray[VR_CIF_HANDLER_IN+1]);
+}
+
+//
+// close
+//
+void
+OFClose(ihandle id)
+{
+ ULONG argarray[] = { (ULONG)"close",1,1,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (long)id;
+ if (call_firmware(argarray) != 0) {
+ warn("OFClose(%x) failed\n", id);
+ }
+
+}
+//
+//read
+//
+long
+OFRead(
+ ihandle instance_id,
+ PCHAR addr,
+ ULONG len
+ )
+{
+ ULONG argarray[] = { (ULONG)"read",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (long) instance_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+2] = len;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+3]);
+}
+//
+//write
+//
+long
+OFWrite(
+ ihandle instance_id,
+ PCHAR addr,
+ ULONG len
+ )
+{
+ ULONG argarray[] = { (ULONG)"write",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (long) instance_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+2] = len;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+3]);
+}
+//
+// seek
+//
+long
+OFSeek(
+ ihandle instance_id,
+ ULONG poshi,
+ ULONG poslo
+ )
+{
+ ULONG argarray[] = { (ULONG)"seek",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (long) instance_id;
+ argarray[VR_CIF_HANDLER_IN+1] = poshi;
+ argarray[VR_CIF_HANDLER_IN+2] = poslo;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return (argarray[VR_CIF_HANDLER_IN+3]);
+}
+//
+// claim
+//
+ULONG
+OFClaim(
+ PCHAR addr,
+ ULONG size,
+ ULONG align
+ )
+{
+ ULONG argarray[] = { (ULONG)"claim",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+1] = size;
+ argarray[VR_CIF_HANDLER_IN+2] = align;
+ if (call_firmware(argarray) != 0) {
+ return (ULONG)0;
+ }
+ return (argarray[VR_CIF_HANDLER_IN+3]);
+}
+//
+// release
+//
+VOID
+OFRelease(
+ PCHAR addr,
+ ULONG size
+ )
+{
+ ULONG argarray[] = { (ULONG)"release",2,0,0,0};
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+1] = size;
+ call_firmware(argarray);
+}
+
+//
+// package-to-path
+//
+long
+OFPackageToPath(
+ phandle device_id,
+ char *addr,
+ ULONG buflen
+ )
+{
+ ULONG argarray[] = { (ULONG)"package-to-path",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)device_id;
+ argarray[VR_CIF_HANDLER_IN+1] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+2] = buflen;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return ((LONG)argarray[VR_CIF_HANDLER_IN+3]);
+}
+
+//
+// instance-to-path
+//
+long
+OFInstanceToPath(
+ ihandle ih,
+ char *addr,
+ ULONG buflen
+ )
+{
+ ULONG argarray[] = { (ULONG)"instance-to-path",3,1,0,0,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)ih;
+ argarray[VR_CIF_HANDLER_IN+1] = (ULONG)addr;
+ argarray[VR_CIF_HANDLER_IN+2] = buflen;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return ((LONG)argarray[VR_CIF_HANDLER_IN+3]);
+}
+
+//
+// instance-to-package
+//
+phandle
+OFInstanceToPackage(ihandle ih)
+{
+ ULONG argarray[] = { (ULONG)"instance-to-package",1,1,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)ih;
+ if (call_firmware(argarray) != 0) {
+ return (-1);
+ }
+ return ((LONG)argarray[VR_CIF_HANDLER_IN+1]);
+}
+
+//
+// call-method
+//
+long
+OFCallMethod(
+ ULONG n_outs,
+ ULONG n_ins,
+ ULONG *outp,
+ char *method,
+ ihandle id,
+ ...
+ )
+{
+ ULONG *argarray, i;
+ va_list ins;
+ int res;
+
+ argarray = (ULONG *) zalloc((n_ins + n_outs + 4) * sizeof(ULONG));
+ argarray[0] = (ULONG) "call-method";
+ argarray[1] = (ULONG) n_ins;
+ argarray[2] = (ULONG) n_outs + 1;
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)method;
+ argarray[VR_CIF_HANDLER_IN+1] = (ULONG)id;
+ va_start(ins, id);
+ for (i = 2; i < n_ins; ++i) {
+ argarray[VR_CIF_HANDLER_IN+i] = va_arg(ins, ULONG);
+ }
+ va_end(ins);
+
+ if ((res = call_firmware(argarray)) != 0) {
+ debug(VRDBG_OF, "OFCallMethod: call_firmware() != 0\n");
+ return (-1);
+ }
+ debug(VRDBG_OF, "OFCallMethod: catch_res %x return %x\n",
+ argarray[VR_CIF_HANDLER_IN+n_ins],
+ argarray[VR_CIF_HANDLER_IN+n_ins+1]);
+ for (i = 0; i < n_outs; ++i)
+ outp[i] = argarray[VR_CIF_HANDLER_IN + n_ins + 1 + i];
+ return ((LONG)argarray[VR_CIF_HANDLER_IN+n_ins]);
+}
+
+//
+// interpret
+//
+long
+OFInterpret(
+ ULONG n_outs,
+ ULONG n_ins,
+ ULONG *outp,
+ char *cmd,
+ ...
+ )
+{
+ ULONG *argarray, i;
+ va_list ins;
+ int res;
+
+ argarray = (ULONG *) zalloc((n_ins + (n_outs + 1) + 3) * sizeof(ULONG));
+ argarray[0] = (ULONG) "interpret";
+ argarray[1] = (ULONG) n_ins;
+ argarray[2] = (ULONG) n_outs + 1;
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)cmd;
+ va_start(ins, cmd);
+ for (i = 1; i < n_ins; ++i) {
+ argarray[VR_CIF_HANDLER_IN+i] = va_arg(ins, ULONG);
+ }
+ va_end(ins);
+
+ if ((res = call_firmware(argarray)) != 0) {
+ debug(VRDBG_OF, "OFCallMethod: call_firmware() != 0\n");
+ return (-1);
+ }
+ debug(VRDBG_OF, "OFCallMethod: catch_res %x return %x\n",
+ argarray[VR_CIF_HANDLER_IN+n_ins],
+ argarray[VR_CIF_HANDLER_IN+n_ins+1]);
+ for (i = 0; i < n_outs; ++i)
+ outp[i] = argarray[VR_CIF_HANDLER_IN + n_ins + 1 + i];
+ return ((LONG)argarray[VR_CIF_HANDLER_IN+n_ins]);
+}
+
+//
+// milliseconds
+//
+ULONG
+OFMilliseconds( VOID )
+{
+ ULONG argarray[] = { (ULONG)"milliseconds",0,1,0};
+ if (call_firmware(argarray) != 0) {
+ return (ULONG)0;
+ }
+ return (argarray[VR_CIF_HANDLER_IN+0]);
+}
+
+
+//
+// boot
+//
+VOID
+OFBoot(
+ char *bootspec
+ )
+{
+ ULONG argarray[] = { (ULONG)"boot",1,0,0};
+
+ argarray[VR_CIF_HANDLER_IN+0] = (ULONG)bootspec;
+ call_firmware(argarray);
+}
+
+
+//
+// enter
+//
+VOID
+OFEnter( VOID )
+{
+ ULONG argarray[] = { (ULONG)"enter",0,0};
+
+ call_firmware(argarray);
+}
+
+
+//
+// exit
+//
+VOID
+OFExit( VOID )
+{
+ ULONG argarray[] = { (ULONG)"exit",0,0};
+
+ warn("Program complete - please reboot.\n");
+ call_firmware(argarray);
+}
diff --git a/private/ntos/boot/veneer/vrdisp.c b/private/ntos/boot/veneer/vrdisp.c
new file mode 100644
index 000000000..e158c677e
--- /dev/null
+++ b/private/ntos/boot/veneer/vrdisp.c
@@ -0,0 +1,169 @@
+/*
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrdisp.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/04/15 02:56:02 $
+ * $Locker: $
+ *
+ *
+ *
+ * Module Name:
+ * vrdisp.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 16-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * Returned always EINVAL in VrTestUnicodeCharacter().
+ * 18-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added for DispalDevice flag.
+ * Added some comments.
+ * 05-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Created roughly.
+ *
+ */
+
+
+#include "veneer.h"
+
+
+//
+// Static data.
+//
+STATIC ARC_DISPLAY_STATUS DisplayStatus = {
+ //
+ // Assume bold, (1), white, (7), foreground and blue, (4)
+ // background because the only known programs that use the
+ // "get current colors" feature is arcinst which uses white
+ // on blue. Anyway, every other Microsoft ARC client we have
+ // seen uses the same color scheme.
+ //
+ 0, 0, 80, 32, 7, 4, 1, 0, 0
+};
+
+
+/*
+ * Name: VrGetDisplayStatus
+ *
+ * Description:
+ * This function returns a pointer to a display status structure.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ *
+ * Return Value:
+ * If the device associated with FileId is not a display device
+ * or is not a valid file descriptor, then return a null pointer.
+ * Otherwise, returns the display status structure.
+ *
+ */
+PARC_DISPLAY_STATUS
+VrGetDisplayStatus(
+ IN ULONG FileId
+ )
+{
+ PARC_DISPLAY_STATUS PDisplayStatus = &DisplayStatus;
+ phandle ph;
+ int lines;
+
+ if (FileId == 1) { // stdout
+ ph = OFFinddevice("/chosen");
+ lines = get_int_prop(ph, "stdout-#lines");
+ if (lines != -1) {
+ PDisplayStatus->CursorMaxYPosition = lines;
+ }
+ return PDisplayStatus;
+ }
+ if (FileId >= FILE_TABLE_SIZE) {
+ return (PARC_DISPLAY_STATUS)NULL;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1
+ && FileTable[FileId].Flags.Write == 1)) {
+
+ return (PARC_DISPLAY_STATUS)NULL;
+ }
+ if (FileTable[FileId].Flags.DisplayDevice != 1) {
+ return (PARC_DISPLAY_STATUS)NULL;
+ }
+
+ ph = OFInstanceToPackage(FileTable[FileId].IHandle);
+ lines = get_int_prop(ph, "stdout-#lines");
+ if (lines != -1) {
+ PDisplayStatus->CursorMaxYPosition = lines;
+ }
+
+ return PDisplayStatus;
+}
+
+
+/*
+ * Name: VrTestUnicodeCharacter
+ *
+ * Description:
+ * This function tests whether or not the display driver associated
+ * with FileId is capable of rendering the Unicode character.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * UnicodeCharacter - Supplies the character to be tested.
+ *
+ * Return Value:
+ *
+ */
+ARC_STATUS
+VrTestUnicodeCharacter(
+ IN ULONG FileId,
+ IN WCHAR UnicodeCharacter
+ )
+{
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (!((FileTable[FileId].Flags.Open == 1) &&
+ (FileTable[FileId].Flags.Write == 1))) {
+
+ return EBADF;
+ }
+ if (FileTable[FileId].Flags.DisplayDevice != 1) {
+ return EBADF;
+ }
+
+ //
+ // Open Firmware has not capability to render any Unicode character.
+ // But it supports 8-bit through. (Mr. Tooch said. '94.06.15)
+ //
+ return EINVAL;
+}
+
+
+/*
+ * Name: VrDisplayInitialize
+ *
+ * Description:
+ * This function initializes the Dispaly entry points in the firmware
+ * transfer vector.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrDisplayInitialize(
+ VOID
+ )
+{
+ debug(VRDBG_ENTRY, "VrDisplayInitialize BEGIN.....\n");
+ //
+ // Initialize the Display entry points in the firmware transfer vector.
+ //
+ (PARC_GET_DISPLAY_STATUS_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetDisplayStatusRoutine] =
+ VrGetDisplayStatus;
+ debug(VRDBG_ENTRY, "VrDisplayInitialize .....END\n");
+}
diff --git a/private/ntos/boot/veneer/vrdumptr.c b/private/ntos/boot/veneer/vrdumptr.c
new file mode 100644
index 000000000..fc789a72d
--- /dev/null
+++ b/private/ntos/boot/veneer/vrdumptr.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrdumptr.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/02/17 00:35:53 $
+ * $Locker: $
+ *
+ *
+ *
+ * Module Name:
+ * vrdumptr.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 11-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Created.
+ *
+ */
+
+
+#include "veneer.h"
+
+PCHAR
+ClassTable[] = {"System",
+ "Processor",
+ "Cache",
+ "Adapter",
+ "Controller",
+ "Peripheral",
+ "Memory"};
+PCHAR
+TypeTable[] = {"ArcSystem",
+ "CentralProcessor",
+ "FloatingPointProcessor",
+ "PrimaryIcache",
+ "PrimaryDcache",
+ "SecondaryIcache",
+ "SecondaryDcache",
+ "SecondaryCache",
+ "EisaAdapter",
+ "TcAdapter",
+ "ScsiAdapter",
+ "DtiAdapter",
+ "MultiFunctionAdapter",
+ "DiskController",
+ "TapeController",
+ "CdromController",
+ "WormController",
+ "SerialController",
+ "NetworkController",
+ "DisplayController",
+ "ParallelController",
+ "PointerController",
+ "KeyboardController",
+ "AudioController",
+ "OtherController",
+ "DiskPeripheral",
+ "FloppyDiskPeripheral",
+ "TapePeripheral",
+ "ModemPeripheral",
+ "MonitorPeripheral",
+ "PrinterPeripheral",
+ "PointerPeripheral",
+ "KeyboardPeripheral",
+ "TerminalPeripheral",
+ "OtherPeripheral",
+ "LinePeripheral",
+ "NetworkPeripheral",
+ "SystemMemory"};
+PCHAR
+ResourceTypeTable[]
+ = {"CmResourceTypeNull",
+ "CmResourceTypePort",
+ "CmResourceTypeInterrupt",
+ "CmResourceTypeMemory",
+ "CmResourceTypeDma",
+ "CmResourceTypeDeviceSpecific"};
+PCHAR
+ShareDispositionTable[]
+ = {"CmResourceShareUndetermined",
+ "CmResourceShareDeviceExclusive",
+ "CmResourceShareDriverExclusive",
+ "CmResourceShareShared"};
+
+STATIC VOID DisplayConfData(PCM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+VOID
+quick_dump_tree(PCONFIGURATION_NODE node)
+{
+ PCONFIGURATION_COMPONENT P = &node->Component;
+ extern int level;
+
+ if (P->IdentifierLength) {
+ debug(VRDBG_CONFIG, "%x %s %s(%d) [%s]\n", node,
+ TypeTable[P->Type], node->ComponentName, P->Key,
+ P->Identifier);
+ } else {
+ debug(VRDBG_CONFIG, "%x %s %s(%d)\n", node,
+ TypeTable[P->Type], node->ComponentName, P->Key);
+ }
+
+ if (node->Child) {
+ ++level;
+ quick_dump_tree(node->Child);
+ --level;
+ }
+ if (node->Peer) {
+ quick_dump_tree(node->Peer);
+ }
+}
+
+VOID
+dump_tree(PCONFIGURATION_NODE node)
+{
+ debug(VRDBG_DUMP, "\n");
+ debug(VRDBG_DUMP, "dump_tree %x '%s'\n", node, node->ComponentName);
+ debug(VRDBG_DUMP, "\tparent '%s' peer '%s' child '%s'\n",
+ node->Parent ? node->Parent->ComponentName : "",
+ node->Peer ? node->Peer->ComponentName : "",
+ node->Child ? node->Child->ComponentName : "");
+ DisplayConfig(&node->Component);
+
+ if (node->Child) {
+ dump_tree(node->Child);
+ }
+ if (node->Peer) {
+ dump_tree(node->Peer);
+ }
+}
+
+VOID
+DisplayConfig(
+ PCONFIGURATION_COMPONENT P
+ )
+{
+ PCM_PARTIAL_RESOURCE_LIST ConfList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR ConfData;
+ int count;
+
+ warn("\tClass=%s, Type=%s, Key=0x%x, Flags=0x%x\n",
+ ClassTable[P->Class], TypeTable[P->Type], P->Key, P->Flags);
+ warn(
+ "\tVersion=%d, Revision=%d, AffinityMask=0x%x\n",
+ P->Version, P->Revision, P->AffinityMask);
+ warn("\tIdentifierLength=%d, Identifier='%s'\n",
+ P->IdentifierLength,
+ P->IdentifierLength ? P->Identifier : "");
+
+ count = P->ConfigurationDataLength;
+ warn("\tConfLen=%d\n", count);
+ if (count == 0) {
+ return;
+ }
+
+ ConfList =
+ (PCM_PARTIAL_RESOURCE_LIST)malloc(count);
+ if (VrGetConfigurationData(ConfList, P)) {
+ free((char *) ConfList);
+ return;
+ }
+
+ warn("\tVersion=%d, Revision=%d, Count=%d\n",
+ ConfList->Version, ConfList->Revision, ConfList->Count);
+ if (ConfList->Version == 1 && ConfList->Revision == 0) {
+ // pre-803 releases
+ free((char *) ConfList);
+ return;
+ }
+ count = ConfList->Count;
+ ConfData = ConfList->PartialDescriptors;
+ while (count-- > 0) {
+ warn(
+ "\t\tType=%s\n\t\tShareDesposition=%s\n\t\tFlags=0x%x",
+ ResourceTypeTable[ConfData->Type],
+ ShareDispositionTable[ConfData->ShareDisposition],
+ ConfData->Flags);
+ if (ConfData->Type == CmResourceTypeDeviceSpecific) {
+ int len = ConfData->u.DeviceSpecificData.DataSize;
+ int *data = (int *) ((char *) ConfData +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+ warn(" Data length=%d", len);
+ while (len > 0) {
+ warn( "\n\t\t%x %x %x", *data, *(data+1), *(data+2));
+ len -= 3 * sizeof(int);
+ data += 3;
+ }
+ ConfData += 1;
+ (char *) ConfData = (char *) ConfData + len;
+ warn("\n");
+ } else {
+ warn( "\n\t\t%x %x %x\n", ConfData->u.Dma.Channel,
+ ConfData->u.Dma.Port, ConfData->u.Dma.Reserved1);
+ ConfData += 1;
+ }
+ }
+ free((char *) ConfList);
+}
+
+STATIC VOID
+DisplayConfData(
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR P
+ )
+{
+ warn("\nType=%s, ShareDesposition=%s, Flags=0x%x\n",
+ ResourceTypeTable[P->Type],
+ ShareDispositionTable[P->ShareDisposition], P->Flags);
+}
diff --git a/private/ntos/boot/veneer/vrenv.c b/private/ntos/boot/veneer/vrenv.c
new file mode 100644
index 000000000..5f8a4a9e3
--- /dev/null
+++ b/private/ntos/boot/veneer/vrenv.c
@@ -0,0 +1,254 @@
+/*++
+ *
+ * Copyright (c) 1994 FirePower Systems, Inc.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrenv.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/06/19 23:13:26 $
+ * $Locker: $
+ *
+
+
+Module Name:
+
+ vrenv.c
+
+Abstract:
+
+ This module contains environment variable functions.
+
+Author:
+
+ A. Benjamin 9-May-1994
+
+Revision History:
+08-08-94 Shin Iwamoto at FirePower Systems Inc.
+ Made OptionsPhandle global static, and set the vales
+ in VrEnvInitialize.
+07-21-94 Shin Iwamoto at FirePower Systems Inc.
+ Added VrEnvInitialize().
+
+--*/
+
+
+#include "veneer.h"
+#define MAX_ARGC 16
+#define MAX_ENVC 16
+
+extern char *VrArgv[MAX_ARGC], *VrEnvp[MAX_ENVC];
+STATIC phandle OptionsPhandle = 0;
+STATIC VOID VrEnvOpen(VOID);
+PCHAR FindInLocalEnv( PCHAR Variable );
+PCHAR ConvertToUpper( PCHAR Orig );
+PCHAR GetEnvVar( PCHAR Variable );
+PCHAR VrCanonicalName( IN PCHAR Variable);
+
+PCHAR
+VrCanonicalName(
+ IN PCHAR Variable
+ )
+{
+ static char CanonicalName[32];
+
+ if (strlen(Variable) > 31) {
+ fatal(
+ "Veneer: Environment variable name %s is longer than 31 characters\n",
+ Variable);
+ }
+ strcpy(CanonicalName, Variable);
+ return (capitalize(CanonicalName));
+}
+
+/*
+ *
+ * ROUTINE: VrGetEnvironmentVariable( PCHAR Variable )
+ *
+ * DESCRIPTION:
+ * Exported Interface to an arc program. This routine will check
+ * the environment passed to the program for the variable before calling
+ * back into the firmware. Since ARC enforces no case sensitivity on
+ * variables, this routine will force all variables to upper case before
+ * checking the local environment.
+ *
+ */
+
+PCHAR
+VrGetEnvironmentVariable(
+ IN PCHAR Variable
+ )
+{
+ PCHAR Value = NULL;
+
+
+ debug(VRDBG_ENV, "VrGetEnvironmentVariable: Entry - Variable: '%s'\n",
+ Variable ? Variable : "NULL");
+
+ if ((Value = FindInLocalEnv(Variable)) == NULL) {
+ Value = GetEnvVar(Variable);
+ }
+
+ debug(VRDBG_ENV, "VrGetEnvironmentVariable: Exit '%s'\n",
+ Value ? Value : "NULL");
+ return Value;
+}
+
+
+ARC_STATUS
+VrSetEnvironmentVariable(
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+{
+ long retval;
+
+ debug(VRDBG_ENV,
+ "VrSetEnvironmentVariable: Entry - Variable: '%s' Value '%s'\n",
+ Variable, Value);
+
+ if (OptionsPhandle == 0) {
+ VrEnvOpen();
+ }
+ retval = OFSetprop(OptionsPhandle, VrCanonicalName(Variable),
+ Value, strlen(Value));
+ retval = (retval != (long) strlen(Value));
+
+ debug(VRDBG_ENV, "VrGetEnvironmentVariable: Exit '%s'\n", retval);
+ return retval;
+}
+
+
+/*
+ * Name: VrEnvInitialize
+ *
+ * Description:
+ * This function initializes the Environment entry points in the firmware
+ * transfer vector and the file table.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrEnvInitialize(VOID)
+{
+ //
+ // Initialize the I/O entry points in the firmware transfer vector.
+ //
+ debug(VRDBG_ENTRY, "VrEnvInitialize: BEGIN......\n");
+ (PARC_GET_ENVIRONMENT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetEnvironmentRoutine]
+ = VrGetEnvironmentVariable;
+ (PARC_SET_ENVIRONMENT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[SetEnvironmentRoutine]
+ = VrSetEnvironmentVariable;
+ debug(VRDBG_ENTRY, "VrEnvInitialize: .....END\n");
+}
+
+/*
+ * Name: VrEnvOpen
+ *
+ * Description:
+ * This function gets the phandle for the Open Firmware options node
+ * so that Open Firmware configuration variables can be later accessed.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+STATIC VOID
+VrEnvOpen(VOID)
+{
+ OptionsPhandle = OFFinddevice("/options");
+ if (OptionsPhandle == 0) {
+ fatal("Veneer: Cannot access /options\n");
+ }
+}
+
+/*
+ * ROUTINE: FindInLocalEnv( PCHAR Variable )
+ *
+ * DESCRIPTION:
+ * Force the passed in variable to upper case, check the local environ-
+ * ment array for this variable and return it's contents if found. Assume
+ * that the environment array is all upper case, at least for the key.
+ *
+ * RETURN:
+ * returns a pointer to data of type CHAR. Null if no var found.
+ */
+
+PCHAR
+FindInLocalEnv(
+ IN PCHAR Variable
+ )
+{
+ PCHAR Value = NULL;
+ PCHAR alpha;
+ ULONG count=0,i=0;
+
+ //
+ // set the incoming variable to all upper case...
+ //
+ alpha = VrCanonicalName(Variable);
+ debug(VRDBG_ENV, "FindInLocalEnv: Entry - Variable: '%s'\n",alpha);
+
+ //
+ // Run through the VrEnvp array looking for a match. Since the VrEnvp
+ // array should all be upper case values, we shouldn't need to worry
+ // about case.
+ //
+ while( VrEnvp[count] && *(VrEnvp[count]) ){
+
+ // Compare the capitalized version of the Variable passed in with
+ // each entry in the VrEnvp array for a length equal to the Variable
+ // less the null terminator.
+ //
+ if (!strncmp(VrEnvp[count], alpha, (strlen(alpha)-1))) {
+ // we've found our match. Now return pointer to this value
+ return(VrEnvp[count]+strlen(alpha));
+ }
+
+ //
+ // reset and try again
+ //
+ count++;
+ }
+
+ //
+ // if we fall out of the loop, it's because we didn't match anything.
+ //
+ return((PCHAR)NULL);
+}
+
+/*
+ * ROUTINE: GetEnvVar( PCHAR Variable )
+ *
+ * DESCRIPTION:
+ * This call is an internal only call that actually delves into the
+ * OpenFirmware to retrieve a value.
+ *
+ * RETURN:
+ * returns a pointer to data of type CHAR. Null if no var found. The
+ * returned value is the contents of the variable found.
+ */
+PCHAR
+GetEnvVar(
+ IN PCHAR Variable
+ )
+{
+ PCHAR Value = NULL;
+
+ debug(VRDBG_ENV, "GetEnvVar: Entry - Variable: '%s'\n",Variable);
+ if (OptionsPhandle == 0) {
+ VrEnvOpen();
+ }
+ Value= get_str_prop(OptionsPhandle, VrCanonicalName(Variable), NOALLOC);
+ return Value;
+}
+
diff --git a/private/ntos/boot/veneer/vrheader.h b/private/ntos/boot/veneer/vrheader.h
new file mode 100644
index 000000000..8f757bb1e
--- /dev/null
+++ b/private/ntos/boot/veneer/vrheader.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrheader.h $
+ * $Revision: 1.10 $
+ * $Date: 1996/01/11 08:03:25 $
+ * $Locker: $
+ *
+ */
+
+/*
+ * From nt/public/sdk/inc/ntdef.h
+ */
+
+//
+// Physical address.
+//
+
+typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
+
+//
+// Cardinal Data Types [0 - 2**N-2)
+//
+
+typedef char CCHAR; // winnt
+typedef short CSHORT;
+typedef ULONG CLONG;
+
+typedef CCHAR *PCCHAR;
+typedef CSHORT *PCSHORT;
+typedef CLONG *PCLONG;
+
+
+
+/*
+ * From nt/public/sdk/inc/ntconfig.h
+ */
+
+//
+// Defines the Type in the RESOURCE_DESCRIPTOR
+//
+
+typedef enum _CM_RESOURCE_TYPE {
+ CmResourceTypeNull = 0, // Reserved
+ CmResourceTypePort,
+ CmResourceTypeInterrupt,
+ CmResourceTypeMemory,
+ CmResourceTypeDma,
+ CmResourceTypeDeviceSpecific,
+ CmResourceTypeMaximum
+} CM_RESOURCE_TYPE;
+
+//
+// Defines the ShareDisposition in the RESOURCE_DESCRIPTOR
+//
+
+typedef enum _CM_SHARE_DISPOSITION {
+ CmResourceShareUndetermined = 0, // Reserved
+ CmResourceShareDeviceExclusive,
+ CmResourceShareDriverExclusive,
+ CmResourceShareShared
+} CM_SHARE_DISPOSITION;
+
+//
+// Define the bit masks for Flags when type is CmResourceTypeInterrupt
+//
+
+#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0
+#define CM_RESOURCE_INTERRUPT_LATCHED 1
+
+//
+// Define the bit masks for Flags when type is CmResourceTypeInterrupt
+//
+
+#define CM_RESOURCE_MEMORY_READ_WRITE 0
+#define CM_RESOURCE_MEMORY_READ_ONLY 1
+#define CM_RESOURCE_MEMORY_WRITE_ONLY 2
+
+//
+// Define the bit masks for Flags when type is CmResourceTypePort
+//
+
+#define CM_RESOURCE_PORT_MEMORY 0
+#define CM_RESOURCE_PORT_IO 1
+
+
+//
+// This structure defines one type of resource used by a driver.
+//
+// There can only be *1* DeviceSpecificData block. It must be located at
+// the end of all resource descriptors in a full descriptor block.
+//
+
+//
+// BUGBUG Make sure alignment is made properly by compiler; otherwise move
+// flags back to the top of the structure (common to all members of the
+// union).
+//
+
+#pragma pack(4)
+typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR {
+ UCHAR Type;
+ UCHAR ShareDisposition;
+ USHORT Flags;
+ union {
+
+ //
+ // Range of port numbers, inclusive. These are physical, bus
+ // relative. The value should be the same as the one passed to
+ // HalTranslateBusAddress().
+ //
+
+ struct {
+ PHYSICAL_ADDRESS Start;
+ ULONG Length;
+ } Port;
+
+ //
+ // IRQL and vector. Should be same values as were passed to
+ // HalGetInterruptVector().
+ //
+
+ struct {
+ ULONG Level;
+ ULONG Vector;
+ ULONG Affinity;
+ } Interrupt;
+
+ //
+ // Range of memory addresses, inclusive. These are physical, bus
+ // relative. The value should be the same as the one passed to
+ // HalTranslateBusAddress().
+ //
+
+ struct {
+ PHYSICAL_ADDRESS Start; // 64 bit physical addresses.
+ ULONG Length;
+ } Memory;
+
+ //
+ // Physical DMA channel.
+ //
+
+ struct {
+ ULONG Channel;
+ ULONG Port;
+ ULONG Reserved1;
+ } Dma;
+
+ //
+ // Device Specific information defined by the driver.
+ // The DataSize field indicates the size of the data in bytes. The
+ // data is located immediately after the DeviceSpecificData field in
+ // the structure.
+ //
+
+ struct {
+ ULONG DataSize;
+ ULONG Reserved1;
+ ULONG Reserved2;
+ } DeviceSpecificData;
+ } u;
+} CM_PARTIAL_RESOURCE_DESCRIPTOR, *PCM_PARTIAL_RESOURCE_DESCRIPTOR;
+#pragma pack()
+
+//
+// A Partial Resource List is what can be found in the ARC firmware
+// or will be generated by ntdetect.com.
+// The configuration manager will transform this structure into a Full
+// resource descriptor when it is about to store it in the regsitry.
+//
+// Note: There must a be a convention to the order of fields of same type,
+// (defined on a device by device basis) so that the fields can make sense
+// to a driver (i.e. when multiple memory ranges are necessary).
+//
+
+typedef struct _CM_PARTIAL_RESOURCE_LIST {
+ USHORT Version;
+ USHORT Revision;
+ ULONG Count;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1];
+} CM_PARTIAL_RESOURCE_LIST, *PCM_PARTIAL_RESOURCE_LIST;
+
+//
+// Define the structures used to interpret configuration data of
+// \\Registry\machine\hardware\description tree.
+// Basically, these structures are used to interpret component
+// sepcific data.
+//
+
+//
+// Define DEVICE_FLAGS
+//
+
+typedef struct _DEVICE_FLAGS {
+ ULONG Failed : 1;
+ ULONG ReadOnly : 1;
+ ULONG Removable : 1;
+ ULONG ConsoleIn : 1;
+ ULONG ConsoleOut : 1;
+ ULONG Input : 1;
+ ULONG Output : 1;
+} DEVICE_FLAGS, *PDEVICE_FLAGS;
+
+//
+// Define Component Information structure
+//
+
+typedef struct _CM_COMPONENT_INFORMATION {
+ DEVICE_FLAGS Flags;
+ ULONG Version;
+ ULONG Key;
+ ULONG AffinityMask;
+} CM_COMPONENT_INFORMATION, *PCM_COMPONENT_INFORMATION;
+
+
+/*
+ * From nt/public/sdk/inc/ntppc.h
+ */
+
+#define KSEG0_BASE 0x00000000 /* ? 0x800000000 */
+
+
+/*
+ * From nt/private/ntos/inc/nthal.h
+ */
+
+//
+// Time conversion routines
+//
+
+typedef struct _TIME_FIELDS {
+ CSHORT Year; // range [1601...]
+ CSHORT Month; // range [1..12]
+ CSHORT Day; // range [1..31]
+ CSHORT Hour; // range [0..23]
+ CSHORT Minute; // range [0..59]
+ CSHORT Second; // range [0..59]
+ CSHORT Milliseconds;// range [0..999]
+ CSHORT Weekday; // range [0..6] == [Sunday..Saturday]
+} TIME_FIELDS;
+typedef TIME_FIELDS *PTIME_FIELDS;
+
+//
+// PowerPC page size = 4 KB
+//
+
+#define PAGE_SIZE (ULONG)0x1000
+
+//
+// Define the number of trailing zeroes in a page aligned virtual address.
+// This is used as the shift count when shifting virtual addresses to
+// virtual page numbers.
+//
+
+#define PAGE_SHIFT 12L
+
+//
+// The device data record for the Floppy peripheral.
+//
+
+typedef struct _CM_FLOPPY_DEVICE_DATA {
+ USHORT Version;
+ USHORT Revision;
+ CHAR Size[8];
+ ULONG MaxDensity;
+ ULONG MountDensity;
+ //
+ // New data fields for version >= 2.0
+ //
+ UCHAR StepRateHeadUnloadTime;
+ UCHAR HeadLoadTime;
+ UCHAR MotorOffTime;
+ UCHAR SectorLengthCode;
+ UCHAR SectorPerTrack;
+ UCHAR ReadWriteGapLength;
+ UCHAR DataTransferLength;
+ UCHAR FormatGapLength;
+ UCHAR FormatFillCharacter;
+ UCHAR HeadSettleTime;
+ UCHAR MotorSettleTime;
+ UCHAR MaximumTrackValue;
+ UCHAR DataTransferRate;
+} CM_FLOPPY_DEVICE_DATA, *PCM_FLOPPY_DEVICE_DATA;
+
+//
+// The device data record for the serial controller.
+//
+
+typedef struct _CM_SERIAL_DEVICE_DATA {
+ USHORT Version;
+ USHORT Revision;
+ ULONG BaudClock;
+} CM_SERIAL_DEVICE_DATA, *PCM_SERIAL_DEVICE_DATA;
+
+/*
+********************************************************************************
+**
+** The following is derived from fparch.h in the nthals\halfire\ppc
+** directory
+**
+**
+**
+********************************************************************************
+*/
+//
+// These names are not sacrosanct, and should be revised upon input from Susan,
+// Jim, and anyone else interested.
+//
+enum scope_use {
+ ENG,
+ MFG,
+ TEST,
+ CUST
+ };
+
+enum rel_state {
+ GENERAL,
+ OFFICIAL,
+ TESTING,
+ CONTROLLED,
+ LAB
+ };
+
+
diff --git a/private/ntos/boot/veneer/vrio.c b/private/ntos/boot/veneer/vrio.c
new file mode 100644
index 000000000..c0a1bd2ae
--- /dev/null
+++ b/private/ntos/boot/veneer/vrio.c
@@ -0,0 +1,1425 @@
+/*
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirePower Systems Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrio.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/04/15 02:55:53 $
+ * $Locker: $
+ *
+ *
+ * Module Name:
+ * vrio.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 26-Sep-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added checking SeekMode in VrSeek().
+ * 15-Sep-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added saving the area pointed to by OpenPath in VrOpen().
+ * 15-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added for XXX_SEEK_IS_BUSTED in VrSeek().
+ * 14-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added ONE_IO_SIZE in VrRead() and VrWrite().
+ * 13-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added ENOSPC checking in VrWrite().
+ * Added for reading ahead in VrGetReadStatus() and VrRead().
+ * 11-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added some debugging facilities in VrOpen. These were
+ * from checked-in veneer source code.
+ * 16-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added when a serial device doesn't read in VrRead().
+ * 15-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * When OpenPath inclues console, the path is for a device.
+ * So, FilePath was set to null.
+ * 13-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added debugging statements.
+ * Modified some porting from Mike Tooch at FirmWorks.
+ * 18-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added for unsinged long size in VrWrite.
+ * Added a part of VrMount.
+ * Added that DirectoryFile flag is ignored in
+ * VrSetFileInformation().
+ * Added for Delete flag in FileTable in
+ * VrRead(), VrWrite(), VrSeek(), VrGetReadStatus()
+ * Added some comments.
+ * and VrSetFileInformation().
+ * 17-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added for NetworkDevice in GetDeviceAttribute().
+ * Added for unsinged long size in VrRead.
+ * 12-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Changed the name, strlen and strncmp to
+ * VfStrlen and VfStrncmp.
+ * 11-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added FIleTable. Changed rootnode to RootNode.
+ * Put cast PCAHR to the first parameter of bzero.
+ * Changed OFPhandle to OfPhandle.
+ * Changed the name of VrFindCOnfigurationNode.
+ * 10-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Changed Vr{Open|Close|Read|Write|Seek} because of
+ * changing the file table structure.
+ * 05-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Created.
+ *
+ */
+
+
+#include "veneer.h"
+
+//
+// Some switches
+//
+
+#define MAX_OPEN_PATH_SIZE MAX_PATH_NAME_SIZE
+#define ONE_IO_SIZE 1024*1024
+
+#define ZERO_LARGE 0
+#define NOT_ZERO_LARGE 1
+
+#define Minimum(X,Y) ((X) < (Y) ? (X) : (Y))
+
+
+//
+// File Table definition
+//
+FILE_TABLE_ENTRY FileTable[FILE_TABLE_SIZE];
+
+
+//
+// Function declarations
+//
+STATIC ARC_STATUS
+GetFileTableEntry(
+ OUT PULONG
+ );
+STATIC ARC_STATUS
+GetDeviceAttribute(
+ IN ULONG,
+ IN PCONFIGURATION_NODE
+ );
+STATIC VOID
+AddLargeInt(
+ PLARGE_INTEGER,
+ PLARGE_INTEGER
+ );
+STATIC VOID
+MoveLargeInt(
+ PLARGE_INTEGER,
+ PLARGE_INTEGER
+ );
+STATIC LONG
+IsLarge(
+ PLARGE_INTEGER
+ );
+STATIC VOID
+DecrementLarge(
+ PLARGE_INTEGER
+ );
+
+
+
+/*
+ * Name: VrOpen
+ *
+ * Description:
+ * This function opens the file specified by OpenPath.
+ * The pathname is translated into the devicename for Open Firmware,
+ * then OFOpen is called with the devicename.
+ *
+ * Arguments:
+ * OpenPath - ARC compliant pathname of the device/file to be opened.
+ * OpenMode - Supplies the mode in which the file is opened.
+ * FileId - Pointer to a variable that receives the fileid for
+ * this pathname.
+ *
+ * Return Value:
+ * If the file is successfully opened returns ESUCCESS otherwise
+ * returns an unsuccessful status.
+ *
+ */
+ARC_STATUS
+VrOpen(
+ IN PCHAR OpenPath,
+ IN OPEN_MODE OpenMode,
+ OUT PULONG FileId
+ )
+{
+ PCHAR FilePath, DevicePath, Partition, Console;
+ ihandle IHandle;
+ ARC_STATUS Status;
+ PCONFIGURATION_NODE ConfNode;
+ PCHAR pstr1;
+ LONG DevSpecLen;
+
+ debug(VRDBG_OPEN, "VrOpen: Entry - Path: %s Mode: %x\n",
+ OpenPath, OpenMode);
+
+ if (strlen(OpenPath) >= MAX_OPEN_PATH_SIZE) {
+ debug(VRDBG_OPEN, "VrOpen: ENAMETOOLONG: '%s'\n", OpenPath);
+ return ENAMETOOLONG;
+ }
+
+ //
+ // Find Partition, Console and FilePath in OpenPath.
+ //
+ FilePath = NULL;
+ Partition = NULL;
+ Console = NULL;
+ for (pstr1 = OpenPath; *pstr1; pstr1++) {
+ if (strncmp(pstr1, "partition", 9) == 0) {
+ Partition = pstr1;
+ while (*pstr1++ != ')') {
+ ;
+ }
+ FilePath = pstr1;
+ break;
+ } else if (strncmp(pstr1, "console", 7) == 0) {
+ Console = pstr1;
+ while (*pstr1++ != ')') {
+ ;
+ }
+ if (*pstr1 != '\0') {
+ return EINVAL;
+ }
+ FilePath = NULL; // Console is a device.
+ break;
+ }
+ else if (*pstr1 == ')') {
+ FilePath = pstr1+1;
+ }
+ }
+ //
+ // Did we eventually wind up with a FilePath after all?
+ //
+ if ((FilePath != NULL) && (strlen(FilePath) == 0)) {
+ FilePath = NULL;
+ }
+ debug(VRDBG_OPEN, "VrOpen: Partition '%s' FilePath '%s'\n",
+ Partition == NULL ? "NULL" : Partition,
+ FilePath == NULL ? "NULL" : FilePath);
+
+ //
+ // Check open mode for a device.
+ //
+ if ((FilePath == NULL) && (OpenMode > ArcOpenReadWrite)) {
+ debug(VRDBG_OPEN, "VrOpen: EINVAL: '%s'\n", OpenPath);
+ return EINVAL;
+ }
+
+ //
+ // Extract the device name from OpenPath.
+ //
+ ConfNode = ArcPathToNode(OpenPath);
+ if (ConfNode == NULL) {
+ debug(VRDBG_OPEN, "VrOpen: ENODEV: '%s'\n", OpenPath);
+ return ENODEV;
+ }
+
+ //
+ // Translate the device name into the device path for Open Firmware.
+ // Add space for the partition and file components.
+ //
+ pstr1 = NodeToPath(ConfNode);
+ DevSpecLen = strlen(pstr1) + 16; // Enough for a partition specifier.
+ if (FilePath != NULL) {
+ DevSpecLen += strlen(FilePath);
+ }
+ DevicePath = zalloc(DevSpecLen);
+ strcpy(DevicePath, pstr1);
+ free(pstr1);
+
+ //
+ // Get a free entry in the file table.
+ //
+ if (Status = GetFileTableEntry(FileId)) {
+ debug(VRDBG_OPEN, "VrOpen: GetFileTableEntry returned %x\n", Status);
+ return Status;
+ }
+
+ //
+ // Set flags in the FileTable.
+ //
+ if (Status = GetDeviceAttribute(*FileId, ConfNode)) {
+ debug(VRDBG_OPEN, "VrOpen: GetDeviceAttribute returned %x\n", Status);
+ return Status;
+ }
+
+ if ((Partition == NULL) && (FilePath == NULL)) { // A device (not file)
+ FileTable[*FileId].Flags.Device = 1;
+ strcat(DevicePath, ":0");
+ } else { // A file (not a device)
+ //
+ // Convert the partition and the filename (if they exist) as follows:
+ //
+ // [partition(key1)][<filepath>]
+ // --> :[key1][,<filepath>]
+ //
+ strcat(DevicePath, ":");
+ if (Partition != NULL) {
+ FileTable[*FileId].Flags.Partition = (FilePath == NULL);
+ pstr1 = Partition;
+ while (*pstr1++ != '(') {
+ ;
+ }
+ if (*pstr1 == ')') {
+ strcat(DevicePath, "0");
+ } else {
+ PCHAR pstr2;
+
+ pstr2 = DevicePath + strlen(DevicePath);
+ do {
+ *pstr2++ = *pstr1++;
+ } while (*pstr1 != ')');
+ *pstr2 = '\0';
+ }
+ }
+ if (FilePath != NULL) {
+ strcat(DevicePath, ",");
+ strcat(DevicePath, FilePath);
+ }
+ }
+
+ //
+ // Now we can open the device path (including the file path).
+ //
+ IHandle = OFOpen(DevicePath);
+ debug(VRDBG_OPEN, "OFOpen: IHandle: %x\n", IHandle);
+ FileTable[*FileId].PathName = DevicePath;
+
+ //
+ // Checking related to OpenMode.
+ //
+ switch (OpenMode) {
+ case ArcCreateWriteOnly:
+ case ArcCreateReadWrite:
+ if (IHandle != 0) {
+ (VOID)OFClose(IHandle);
+ return EACCES;
+ }
+ break;
+ default:
+ if (IHandle == 0) {
+ return EIO;
+ }
+ }
+
+ FileTable[*FileId].Flags.Open = 1;
+ FileTable[*FileId].IHandle = IHandle;
+
+ debug(VRDBG_OPEN, "VrOpen: Exit - FileId: %d IHandle: %x\n",
+ *FileId, IHandle);
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrClose
+ *
+ * Description:
+ * This function closes a file or a device if it is opened.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ *
+ * Return Value:
+ * If the specified file is open, then a close is attempted via
+ * OFClose and ESUCCESS is returned. Otherwise, return an unsuccessful
+ * status.
+ *
+ */
+ARC_STATUS
+VrClose(
+ IN ULONG FileId
+ )
+{
+ debug(VRDBG_OPEN, "VrClose: Entry - FileId: %d\n", FileId);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (FileTable[FileId].Flags.Open != 1) {
+ return EACCES;
+ }
+
+ //
+ // Close the file.
+ //
+ (VOID)OFClose(FileTable[FileId].IHandle);
+
+ //
+ // Release the file table entry.
+ //
+ // FileTable[FileId].Flags.Open = 0;
+ bzero((PCHAR)&FileTable[FileId], sizeof(FILE_TABLE_ENTRY));
+ free(FileTable[FileId].PathName);
+
+ debug(VRDBG_OPEN, "VrClose: Exit\n");
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrRead
+ *
+ * Description:
+ * This function reads data from the device of file specified by FileId
+ * into the buffer pointed to by Buffer.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * Buffer - Supplies a pointer to the buffer that receives the read
+ * data.
+ * Length - Supplies the maximum number of bytes to be read.
+ * If this field contains the value zero, then no bytes
+ * are read.
+ * Count - Supplies a pointer to a variable that receives the number
+ * of bytes actually transfered.
+ *
+ * Return Value:
+ * If the specified file is open for read, then a read is attempted
+ * and the status of the operation is retuned. Otherwise, return
+ * an unsuccessful status.
+ *
+ */
+
+STATIC CHAR consin_readahead = 0;
+
+ARC_STATUS
+VrRead(
+ IN ULONG FileId,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+ LARGE_INTEGER LInteger;
+ PCHAR buf = (PCHAR) Buffer;
+
+ if (FileId == 0) { // stdin
+ if (consin_readahead) {
+ *buf = consin_readahead;
+ consin_readahead = 0;
+ *Count = 1;
+ } else {
+ if (ConsoleIn == 0) {
+ (void) VrFindConsolePath("stdin");
+ }
+ while (((LONG)*Count = OFRead(ConsoleIn, Buffer, Length)) <= 0){
+ ;
+ }
+ }
+ return ESUCCESS;
+ }
+
+ debug(VRDBG_RDWR, "VrRead: Entry - FileId: %d Buf: %x len: %d\n",
+ FileId, Buffer, Length);
+
+ //
+ // If Length is zero, return as if the function were successful.
+ //
+ if (Length == 0) {
+ *Count = 0;
+ return ESUCCESS;
+ }
+ if (FileId == 1) {
+ return EBADF;
+ }
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1
+ && FileTable[FileId].Flags.Read == 1)) {
+ return EACCES;
+ }
+ if (FileTable[FileId].Flags.Delete == 1) {
+ return EACCES;
+ }
+
+#ifdef NO_UNSIGNED_LONG_IO
+ //
+ // Calls the read routine.
+ //
+ (LONG)*Count = OFRead(FileTable[FileId].IHandle, Buffer, Length);
+ if ((LONG)*Count == -1) {
+ return EIO; // XXXX
+ }
+
+#else // NO_UNSIGNED_LONG_IO
+ //
+ // Initialize Counter.
+ //
+ *Count = 0;
+
+ //
+ // Checking read ahead buffer. If already read, the copy the buffer
+ // into Buffer.
+ //
+ if (FileTable[FileId].ReadAheadCount != 0) {
+ *Count = FileTable[FileId].ReadAheadCount;
+ bcopy(FileTable[FileId].ReadAheadBuffer, Buffer, *Count);
+ Buffer = (PCHAR)Buffer + *Count;
+ Length -= *Count;
+ FileTable[FileId].ReadAheadCount = 0;
+ }
+
+ //
+ // Calls the read routine.
+ //
+ while (Length > 0) {
+ LONG SingleReadSize;
+ LONG ReadCount;
+
+ SingleReadSize = Minimum(Length, ONE_IO_SIZE);
+ ReadCount = OFRead(FileTable[FileId].IHandle, Buffer, SingleReadSize);
+ if (ReadCount == -1) {
+ LONG Status;
+
+ //
+ // If an error in the second or later read happes,
+ // the offset must be put back using OFSeek.
+ // In reading ahead, this is useful.
+ //
+ if (*Count != 0) {
+ Status = OFSeek(FileTable[FileId].IHandle,
+ FileTable[FileId].Position.HighPart,
+ FileTable[FileId].Position.LowPart);
+ //
+ // Ignore Status.
+ //
+ }
+ return EIO; // XXXX
+ }
+
+ //
+ // Retry to read, when the device is serial and there is no data.
+ //
+ if ((ReadCount == -2) && (*Count == 0)) {
+ continue;
+ }
+
+ //
+ // Update the number of bytes read successfully.
+ //
+ *Count += ReadCount;
+
+ //
+ // If the device represented by FileId is a network device,
+ // read one time. If not yet read, continue.
+ //
+ if (FileTable[FileId].Flags.NetworkDevice == 1) {
+ if ((ReadCount == 0) && (*Count == 0)) {
+ continue;
+ }
+ return ESUCCESS;
+ }
+
+ //
+ // Find EOF, then break this loop.
+ //
+ if (ReadCount < SingleReadSize) {
+ break;
+ }
+
+ //
+ // Update the remaining length and the buffer to point to
+ // the next position.
+ //
+ Length -= SingleReadSize;
+ Buffer = (PCHAR)Buffer + SingleReadSize;
+ }
+#endif // NO_UNSIGNED_LONG_IO
+
+ //
+ // Calculates the position of the file.
+ //
+ LInteger.HighPart = 0;
+ LInteger.LowPart = *Count;
+ AddLargeInt(&FileTable[FileId].Position, &LInteger);
+
+ debug(VRDBG_RDWR, "VrRead: Exit ReadCount: %d\n", *Count);
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrWrite
+ *
+ * Description:
+ * This function writes data from memory starting from the buffer
+ * pointed to by Buffer to the device specified by FileId.
+ * Upon completion of a successful write, the byte offset for FileId
+ * is updated; otherwise the byte offset is left unchanged.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * Buffer - Supplies a pointer to the buffer that contains
+ * the write data.
+ * Length - Supplies the number of bytes to be written.
+ * Count - Supplies a pointer to a variable that contains
+ * the number of bytes actually transfered.
+ *
+ * Return Value:
+ * If the specified file is open for write, then a write is attempted
+ * using OFWrite and a status is returned. Otherwise, return
+ * an unsuccessful status.
+ *
+ */
+ARC_STATUS
+VrWrite(
+ IN ULONG FileId,
+ IN PVOID Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+ LARGE_INTEGER LInteger;
+ ARC_STATUS Status;
+
+ if (FileId == 1) { // stdout
+ *Count = OFWrite(ConsoleOut, Buffer, Length);
+ return ESUCCESS;
+ }
+
+ debug(VRDBG_RDWR, "VrWrite: Entry - FileId: %d Buf: %x len: %d\n",
+ FileId, Buffer, Length);
+
+ //
+ // If Length is zero, return as if the function were successful.
+ //
+ if (Length == 0) {
+ *Count = 0;
+ return ESUCCESS;
+ }
+ if (FileId == 0) {
+ return EBADF;
+ }
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1
+ && FileTable[FileId].Flags.Write == 1)) {
+ return EACCES;
+ }
+ if (FileTable[FileId].Flags.Delete == 1) {
+ return EACCES;
+ }
+
+ //
+ // If Length bytes cannot be placed into a network packet,
+ // return ENOSPC without sending the packet, placing the number of bytes
+ // that could be written in Count.
+ //
+ if (FileTable[FileId].Flags.NetworkDevice == 1) {
+ ULONG MaxFrameSize;
+
+ MaxFrameSize = get_int_prop(OFFinddevice(FileTable[FileId].PathName),
+ "max-frame-size");
+ if (Length > MaxFrameSize) {
+ *Count = MaxFrameSize;
+ return ENOSPC;
+ }
+ }
+
+#ifdef NO_UNSIGNED_LONG_IO
+ //
+ // Calls the write routine.
+ //
+ Status = ESUCCESS;
+ (LONG)*Count = OFWrite(FileTable[FileId].IHandle, Buffer, Length);
+ if ((LONG)*Count == -1) {
+ return EIO; // XXXX
+ }
+
+#else // NO_UNSIGNED_LONG_IO
+
+ Status = ESUCCESS;
+ *Count = 0;
+ while (Length > 0) {
+ LONG SingleWriteSize;
+ LONG WriteCount;
+
+ SingleWriteSize = Minimum(Length, ONE_IO_SIZE);
+ WriteCount = OFWrite(FileTable[FileId].IHandle, Buffer,
+ SingleWriteSize);
+ if (WriteCount == -1) {
+ LONG SeekStatus;
+
+ //
+ // If an error in the second or later read happens,
+ // the offset must be put back using OFSeek.
+ //
+ if (*Count != 0) {
+ SeekStatus = OFSeek(FileTable[FileId].IHandle,
+ FileTable[FileId].Position.HighPart,
+ FileTable[FileId].Position.LowPart);
+ //
+ // Ignore Status.
+ //
+ }
+ return EIO; // XXXX
+ }
+
+ //
+ // Update the number of bytes written successfully.
+ //
+ *Count += WriteCount;
+
+ //
+ // If the device represented by FileId is a network device,
+ // write one time. If not yet written, continue.
+ //
+ if (FileTable[FileId].Flags.NetworkDevice == 1) {
+ if (WriteCount == 0) {
+ continue;
+ }
+ return ESUCCESS;
+ }
+
+ //
+ // Find that the device is full.
+ //
+ if (WriteCount < SingleWriteSize) {
+ Status = ENOSPC;
+ break;
+ }
+
+ //
+ // Update the remaining length and the buffer to point to
+ // the next position.
+ //
+ Length -= SingleWriteSize;
+ Buffer = (PCHAR)Buffer + SingleWriteSize;
+ }
+#endif // NO_UNSIGNED_LONG_IO
+
+ //
+ // Calculates the position of the file.
+ //
+ LInteger.HighPart = 0;
+ LInteger.LowPart = *Count;
+ AddLargeInt(&FileTable[FileId].Position, &LInteger);
+
+ if (FileId >= 2) {
+ debug(VRDBG_RDWR, "VrWrite: Exit WrtCount: %d, Status: %d\n",
+ *Count, Status);
+ }
+
+ return Status;
+}
+
+
+/*
+ * Name: VrMount
+ *
+ * Description:
+ * This function is used to load and unload media for devices that
+ * support removale media.
+ *
+ * Arguments:
+ * MountPath - Supplies a pointer to the variable that contains
+ * the path of the device.
+ * Operation - Supplies a indication whether the media is to be
+ * loaded or unloaded.
+ *
+ * Return Value:
+ * If the specified path is for device, then a mount is attempted
+ * a status is returned. Otherwise, return an unsuccessful status.
+ *
+ */
+ARC_STATUS
+VrMount(
+ IN PCHAR MountPath,
+ IN MOUNT_OPERATION Operation
+ )
+{
+ PCONFIGURATION_NODE ConfNode;
+ PCHAR FilePath, pstr1;
+
+ debug(VRDBG_OPEN, "VrMount: Entry - MountPath: %s Operation: %d\n",
+ MountPath, Operation);
+
+ //
+ // Check that the MountPath is a device.
+ //
+ FilePath = MountPath;
+ for (pstr1 = MountPath; *pstr1; pstr1++) {
+ if (strncmp(pstr1, "partition", 9) == 0) {
+ return EINVAL;
+ } else if (strncmp(pstr1, "console", 7) == 0) {
+ return EINVAL;
+ } else if (*pstr1 == ')') {
+ FilePath = pstr1+1;
+ }
+ }
+ if (FilePath == MountPath || FilePath[0] != '\0') {
+ return EINVAL;
+ }
+
+ //
+ // Find the configuration node using the MountPath.
+ //
+ ConfNode = ArcPathToNode(MountPath);
+ if (ConfNode == NULL) {
+ return ENOENT;
+ }
+
+ //
+ // Check that the device is removable.
+ //
+ if (!(ConfNode->Component.Flags.Removable)) {
+ return ENOENT; // XXXX
+ }
+
+ //
+ // Translate the device name into the device path for Open Firmware.
+ //
+ // XXXX
+ // How do I mount/unmount ?
+ // If Operation is MountUnloadMedia for not mounted device,
+ // return ENXIO;
+
+ debug(VRDBG_OPEN, "VrMount: Exit\n");
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrSeek
+ *
+ * Description:
+ * This function changes the byte offset associated with the device,
+ * partition, or file specified by FileId.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * Offset - Supplies a poiner to a structure that contains
+ * the offset value.
+ * SeekMode - Supplies the type of positioning to be performed.
+ *
+ * Return Value:
+ * If the specified file is open, then a seek is attempted and
+ * the status of the operation is returned. Otherwise, return
+ * an unsuccessful status.
+ *
+ */
+ARC_STATUS
+VrSeek(
+ IN ULONG FileId,
+ IN PLARGE_INTEGER Offset,
+ IN SEEK_MODE SeekMode
+ )
+{
+ LONG Status;
+
+ debug(VRDBG_RDWR, "VrSeek: Entry - FileId: %d Offset: %x.%x Mode: %x\n",
+ FileId, Offset->HighPart, Offset->LowPart, SeekMode);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (FileTable[FileId].Flags.Open != 1) {
+ return EACCES;
+ }
+ if (FileTable[FileId].Flags.Delete == 1) {
+ return EACCES;
+ }
+ if (!(SeekMode == SeekRelative || SeekMode == SeekAbsolute)) {
+ return EINVAL;
+ }
+
+ //
+ // If the specified device is Network, only set Offset into FileTable
+ // because the Offset is interpreted to be a count of input to ignore.
+ // The offset is cleared after reading the input packet.
+ //
+ if (FileTable[FileId].Flags.NetworkDevice == 1) {
+ (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset);
+ return ESUCCESS;
+ }
+
+ //
+ // Set the file position according to SeekMode.
+ //
+ if (SeekMode == SeekRelative) {
+ (VOID)AddLargeInt(&FileTable[FileId].Position, Offset);
+ } else {
+ (VOID)MoveLargeInt(&FileTable[FileId].Position, Offset);
+ }
+
+ //
+ // If FileId is for Network device, the input packets are ignored
+ // according to Offset and then return with ESUCCESS.
+ //
+ if (FileTable[FileId].Flags.NetworkDevice == 1) {
+ while (IsLarge(&FileTable[FileId].Position) == NOT_ZERO_LARGE) {
+ LONG ReadSize;
+ CHAR Buffer[4];
+
+ if ((ReadSize = OFRead(FileTable[FileId].IHandle, Buffer, 1))
+ == -1) {
+ return EIO;
+ }
+ if (ReadSize == 0) {
+ continue;
+ }
+ DecrementLarge(&FileTable[FileId].Position);
+ }
+ return ESUCCESS;
+ }
+
+ Status = OFSeek(FileTable[FileId].IHandle,
+ FileTable[FileId].Position.HighPart,
+ FileTable[FileId].Position.LowPart);
+ if (Status == -1) {
+ return EINVAL; // XXXX
+ }
+
+ debug(VRDBG_RDWR, "VrSeek: Exit\n");
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrGetDirectoryEntry
+ *
+ * Description:
+ * This function reads directory entries from the system partition
+ * directory file specified by FileId.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * Buffer - Supplies a pointer to a buffer for the entry data.
+ * Length - Supplies the number of entries to retrieve.
+ * Count - Supplies a pointeer to the number of entries read
+ * into the buffer.
+ *
+ * Return Value:
+ * If the specified file is open for read, then the read is attempted
+ * and the status is returned. Otherwise, retrun an unsuccessful status.
+ *
+ */
+ARC_STATUS
+VrGetDirectoryEntry(
+ IN ULONG FileId,
+ OUT PDIRECTORY_ENTRY Buffer,
+ IN ULONG Length,
+ OUT PULONG Count
+ )
+{
+ debug(VRDBG_OPEN, "VrGetDirectoryEntry: Entry - FileId: %d Length: %d\n",
+ FileId, Length);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (FileTable[FileId].Flags.Device) {
+ return ENOTDIR;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1
+ && FileTable[FileId].Flags.Read == 1)) {
+ return EBADF;
+ }
+
+ // XXXX
+ // Get Director Entry if (FileID != directory) return ENOTDIR;
+
+ debug(VRDBG_OPEN, "VrGetDirectoryEntry: Exit\n");
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrGetFileInformation
+ *
+ * Description:
+ * This function retunrs an information structure about the specified
+ * file or partition.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * FileInformation - Supplies a pointer to the location of the file
+ * information data.
+ *
+ * Return Value:
+ * If the specified file is open, then getting the file information is
+ * attempted and the status is returned. Otherwise, retrun an unsuccessful
+ * status.
+ *
+ */
+ARC_STATUS
+VrGetFileInformation(
+ IN ULONG FileId,
+ OUT PFILE_INFORMATION pFI
+ )
+{
+ PFILE_TABLE_ENTRY fte;
+ ihandle ih;
+ PCONFIGURATION_NODE node;
+ ULONG size_thang[2];
+
+ debug(VRDBG_OPEN, "VrGetFileInformation: Entry - FileId: %d\n", FileId);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ debug(VRDBG_OPEN, "VrGetFileInformation: Exit EBADF\n");
+ return EBADF;
+ }
+ fte = &FileTable[FileId];
+ if (fte->Flags.Open != 1) {
+ debug(VRDBG_OPEN, "VrGetFileInformation: Exit EACCES\n");
+ return EACCES;
+ }
+ if (fte->Flags.Device == 1) {
+ debug(VRDBG_OPEN, "VrGetFileInformation: Exit EINVAL\n");
+ return EINVAL;
+ }
+
+ ih = fte->IHandle;
+ node = InstanceToNode(ih);
+ pFI->CurrentPosition = fte->Position;
+ pFI->Type = node->Component.Type;
+
+ (void) OFCallMethod(2, 2, size_thang, "size", ih);
+ pFI->EndingAddress.HighPart = size_thang[0];
+ pFI->EndingAddress.LowPart = size_thang[1];
+
+ if (fte->Flags.Partition == 1) {
+ (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.HighPart),
+ "offset-high", ih);
+ (void) OFCallMethod( 1, 2, &(pFI->StartingAddress.LowPart),
+ "offset-low", ih);
+ AddLargeInt(&pFI->EndingAddress, &pFI->StartingAddress);
+ pFI->FileName[0] = '\0';
+ pFI->FileNameLength = 0;
+ } else {
+ /*
+ * It's a file.
+ */
+ pFI->StartingAddress.HighPart = 0;
+ pFI->StartingAddress.LowPart = 0;
+ strcpy(pFI->FileName, fte->PathName); // XXX s.b. strncpy(&,&,32)
+ pFI->FileNameLength = strlen(fte->PathName) + 1;
+ }
+#ifdef XXX
+ pFI->Attributes = // Get this from the firmware, somehow.
+#endif
+ debug(VRDBG_OPEN, "VrGetFileInformation:\n");
+ debug(VRDBG_OPEN, "\tStarting %x.%x\n", pFI->StartingAddress.HighPart,
+ pFI->StartingAddress.LowPart);
+ debug(VRDBG_OPEN, "\tEnding %x.%x\n", pFI->EndingAddress.HighPart,
+ pFI->EndingAddress.LowPart);
+ debug(VRDBG_OPEN, "\tCurrent %x.%x\n", pFI->CurrentPosition.HighPart,
+ pFI->CurrentPosition.LowPart);
+ debug(VRDBG_OPEN, "\tType %d FileNameLength %d\n", pFI->Type,
+ pFI->FileNameLength);
+ debug(VRDBG_OPEN, "\tFileName '%s'\n",
+ pFI->FileNameLength ? pFI->FileName : "NULL");
+ return ESUCCESS;
+}
+
+/*
+ * Name: VrGetReadStatus
+ *
+ * Description:
+ * This function determines if any bytes would be returned if a read
+ * operation were performed on FileId.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ *
+ * Return Value:
+ * If the specified file is open, then the getting read status is
+ * attempted and the status is returned. Otherwise, retrun an unsuccessful
+ * status.
+ *
+ */
+ARC_STATUS
+VrGetReadStatus(
+ IN ULONG FileId
+ )
+{
+ LONG Count;
+
+ if (FileId == 0) { // stdin
+ if (consin_readahead != 0) {
+ return (ESUCCESS);
+ }
+ if (ConsoleIn == 0) {
+ (void) VrFindConsolePath("stdin");
+ }
+ if (OFRead(ConsoleIn, &consin_readahead, 1) != 1) {
+ return (EAGAIN);
+ }
+ return (ESUCCESS);
+ }
+
+ debug(VRDBG_RDWR, "VrGetReadStatus: Entry - FileId: %d\n", FileId);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1
+ && FileTable[FileId].Flags.Read == 1)) {
+ return EACCES;
+ }
+ if (FileTable[FileId].Flags.Delete == 1) {
+ return EACCES;
+ }
+
+ //
+ // Try to read one byte.
+ //
+ Count = OFRead(FileTable[FileId].IHandle,
+ FileTable[FileId].ReadAheadBuffer,
+ 1);
+ if (Count != 1) {
+ FileTable[FileId].ReadAheadCount = 0; // For safety.
+ debug(VRDBG_RDWR, "VrGetReadStatus: Exit - with EAGAIN\n");
+ return EAGAIN;
+ }
+
+ //
+ // Now read ahead one byte.
+ //
+ FileTable[FileId].ReadAheadCount = 1;
+
+ if (FileId >= 2) {
+ debug(VRDBG_RDWR, "VrGetReadStatus: Exit\n");
+ }
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrSetFileInformation
+ *
+ * Description:
+ * This function sets the file attributes for the specified FileId.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * AttributeFlags - Supplies the attributes to be set for the file.
+ * AttributeMask - Supplies the attribute Mask.
+ *
+ * Return Value:
+ * If the specified file is open, then the setting file information is
+ * attempted and the status is returned. Otherwise, retrun an unsuccessful
+ * status.
+ *
+ */
+ARC_STATUS
+VrSetFileInformation(
+ IN ULONG FileId,
+ IN ULONG AttributeFlags,
+ IN ULONG AttributeMask
+ )
+{
+ debug(VRDBG_OPEN, "VrSetFileInformation: Entry - FileId: %d AttributeFlags: %x AttributeMask: %x\n",
+ FileId, AttributeFlags, AttributeMask);
+
+ if (FileId >= FILE_TABLE_SIZE) {
+ return EBADF;
+ }
+ if (!(FileTable[FileId].Flags.Open == 1)) {
+ return EACCES;
+ }
+ if (FileTable[FileId].Flags.Device == 1) {
+ return EINVAL;
+ }
+
+ //
+ // The attribute DirectoryFile is ignored for this function.
+ //
+ AttributeMask &= ~ArcDirectoryFile;
+
+ //
+ // A file is marked for deletion by setting the DeleteFile flag
+ // in voth the AttributeFlags and AttributeMask parameters.
+ // In this case, the file can be access only by Close().
+ //
+ if ((AttributeMask & ArcDeleteFile) && (AttributeFlags & ArcDeleteFile)) {
+
+ //
+ // When the file is a derectroy which is not empty or a read-only file,
+ // EACCESS is retuned.
+ //
+ // XXXX not empy check is needed
+ //
+ if (!(FileTable[FileId].Flags.Read == 1
+ && FileTable[FileId].Flags.Write == 0)) {
+ return EACCES;
+ }
+
+
+ FileTable[FileId].Flags.Delete = 1;
+ }
+
+ // XXX return OFSetFileInformation(FileId, Buffer, Length, Count);
+
+ debug(VRDBG_OPEN, "VrSetFileInformation: Exit\n");
+ return(ESUCCESS);
+}
+
+
+/*
+ * Name: VrIoInitialize
+ *
+ * Description:
+ * This function initializes the I/O entry points in the firmware
+ * transfer vector and the file table.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrIoInitialize(
+ VOID
+ )
+{
+ ULONG Index;
+
+ //
+ // Initialize the I/O entry points in the firmware transfer vector.
+ //
+ debug(VRDBG_ENTRY, "VrIoInitialize BEGIN......\n");
+ (PARC_CLOSE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[CloseRoutine] = VrClose;
+ (PARC_MOUNT_ROUTINE) SYSTEM_BLOCK->FirmwareVector[MountRoutine] = VrMount;
+ (PARC_OPEN_ROUTINE) SYSTEM_BLOCK->FirmwareVector[OpenRoutine] = VrOpen;
+ (PARC_READ_ROUTINE) SYSTEM_BLOCK->FirmwareVector[ReadRoutine] = VrRead;
+ (PARC_SEEK_ROUTINE) SYSTEM_BLOCK->FirmwareVector[SeekRoutine] = VrSeek;
+ (PARC_WRITE_ROUTINE) SYSTEM_BLOCK->FirmwareVector[WriteRoutine] = VrWrite;
+
+ (PARC_READ_STATUS_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[ReadStatusRoutine] = VrGetReadStatus;
+
+ (PARC_GET_FILE_INFO_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetFileInformationRoutine] =
+ VrGetFileInformation;
+ (PARC_SET_FILE_INFO_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[SetFileInformationRoutine] =
+ VrSetFileInformation;
+ (PARC_GET_DIRECTORY_ENTRY_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetDirectoryEntryRoutine] =
+ VrGetDirectoryEntry;
+
+ //
+ // Initialize the file table.
+ //
+ for (Index = 0; Index < FILE_TABLE_SIZE; Index++) {
+ FileTable[Index].Flags.Open = 0;
+ }
+
+ debug(VRDBG_ENTRY, "VrIoInitialize ......END\n");
+ return;
+}
+
+
+/*
+ * Name: GetFileTableEntry (internal)
+ *
+ * Description:
+ * This function looks for an unused entry in the FileTable.
+ *
+ * Arguments:
+ * Entry - Pointer to the variable that gets an index
+ * for the file table.
+ *
+ * Return Value:
+ *
+ * Returns ESUCCESS if a free entry is found
+ * or EMFILE if no entry is available.
+ *
+ */
+STATIC ARC_STATUS
+GetFileTableEntry(
+ OUT PULONG Entry
+ )
+{
+ ULONG Index;
+
+ for (Index = 2; Index < FILE_TABLE_SIZE; Index++) {
+ if (FileTable[Index].Flags.Open == 0) {
+#ifdef notdef
+ FileTable[Index].Position.LowPart = 0;
+ FileTable[Index].Position.HighPart = 0;
+#endif // notdef
+ bzero((PCHAR)&FileTable[Index], sizeof(FILE_TABLE_ENTRY));
+ *Entry = Index;
+ return ESUCCESS;
+ }
+ }
+ return EMFILE;
+}
+
+
+/*
+ * Name: GetDeviceAttribute (internal)
+ *
+ * Description:
+ * This function sets the specified File Table entry to the attribute.
+ *
+ * Arguments:
+ * FileId - Supplies the file table index.
+ * ConfNode - Supplies a pointer to the Configuration Node.
+ *
+ * Return Value:
+ * If the Configuration node is not peripheral, then return ENODEV.
+ * Otherwise, returns ESUCCESS.
+ *
+ */
+STATIC ARC_STATUS
+GetDeviceAttribute(
+ IN ULONG FileId,
+ IN PCONFIGURATION_NODE ConfNode
+ )
+{
+ if (ConfNode->Component.Class != PeripheralClass) {
+ warn("GetDeviceAttribute: node %s(%d) not PeripheralClass.\n",
+ ConfNode->ComponentName, ConfNode->Component.Key);
+ return ENODEV;
+ }
+
+ if (ConfNode->Component.Type == MonitorPeripheral) {
+ FileTable[FileId].Flags.DisplayDevice = 1;
+ }
+ if (ConfNode->Component.Flags.Removable) {
+ FileTable[FileId].Flags.RemovableDevice = 1;
+ }
+ if (ConfNode->Component.Type == NetworkPeripheral) {
+ FileTable[FileId].Flags.NetworkDevice = 1;
+ }
+ if (ConfNode->Component.Flags.Input) {
+ FileTable[FileId].Flags.Read = 1;
+ }
+ if (ConfNode->Component.Flags.Output &&
+ !(ConfNode->Component.Flags.ReadOnly)) {
+ FileTable[FileId].Flags.Write = 1;
+ }
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: AddLargeInt (internal)
+ *
+ * Description:
+ * This function adds a large integer into another large ingeger.
+ *
+ * Arguments:
+ * Position - Supplies a pointer to a variable to be added.
+ * Value - Supplies a pointer to a variable to add.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+STATIC VOID
+AddLargeInt(
+ PLARGE_INTEGER Position,
+ PLARGE_INTEGER Value
+ )
+{
+ if ((Position->LowPart += Value->LowPart) < Value->LowPart) {
+ Position->HighPart++;
+ }
+ Position->HighPart += Value->HighPart;
+}
+
+
+/*
+ * Name: DecrementLarge (internal)
+ *
+ * Description:
+ * This function decrements a large integer.
+ *
+ * Arguments:
+ * Position - Supplies a pointer to a variable to be decremented.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+STATIC VOID
+DecrementLarge(
+ PLARGE_INTEGER Position
+ )
+{
+ ULONG ULong = Position->LowPart;
+
+ Position->LowPart--;
+ if (Position->LowPart > ULong) {
+ Position->HighPart--;
+ }
+}
+
+
+/*
+ * Name: MoveLargeInt (internal)
+ *
+ * Description:
+ * This function copies a large integer into another large ingeger.
+ *
+ * Arguments:
+ * Position - Supplies a pointer to a variable to be copied.
+ * Value - Supplies a pointer to a variable to copy.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+STATIC VOID
+MoveLargeInt(
+ PLARGE_INTEGER Position,
+ PLARGE_INTEGER Value
+ )
+{
+ Position->LowPart = Value->LowPart;
+ Position->HighPart = Value->HighPart;
+}
+
+
+/*
+ * Name: IsLarge (internal)
+ *
+ * Description:
+ * This function determines whether a large integer contains zero.
+ *
+ * Arguments:
+ * Position - Supplies a pointer to a variable to be checked.
+ *
+ * Return Value:
+ * If the large integer is zero, then returns ZERO_LARGE. Otherwise,
+ * returns NOT_ZERO_LARGE.
+ *
+ */
+STATIC LONG
+IsLarge(
+ PLARGE_INTEGER Position
+ )
+{
+ if (Position->LowPart != 0) {
+ return NOT_ZERO_LARGE;
+ }
+ if (Position->HighPart != 0) {
+ return NOT_ZERO_LARGE;
+ }
+ return ZERO_LARGE;
+}
+
diff --git a/private/ntos/boot/veneer/vrlib.c b/private/ntos/boot/veneer/vrlib.c
new file mode 100644
index 000000000..6d8753887
--- /dev/null
+++ b/private/ntos/boot/veneer/vrlib.c
@@ -0,0 +1,614 @@
+/*
+ *
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1996 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrlib.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/06/27 18:36:55 $
+ * $Locker: $
+ */
+
+#include "veneer.h"
+
+STATIC VOID doprnt(VOID (*)(), char *, va_list);
+STATIC VOID printbase(VOID (*)(), ULONG x, int base);
+
+int
+get_bool_prop(phandle node, char *key)
+{
+ return(OFGetproplen(node, key) != -1);
+}
+
+int
+decode_int(UCHAR *p)
+{
+ ULONG i = *p++ << 8;
+ i = (i + *p++) << 8;
+ i = (i + *p++) << 8;
+ return (i + *p);
+}
+
+int
+get_int_prop(phandle node, char *key)
+{
+ int res;
+ char buf[sizeof(int)];
+
+ res = OFGetprop(node, key, buf, sizeof(int));
+ if (res != sizeof(int)) {
+ return(-1);
+ }
+ /*
+ * The NT veneer is always little-endian.
+ */
+ return(decode_int((UCHAR *) buf));
+}
+
+reg *
+decode_reg(UCHAR *buf, int buflen, int addr_cells, int size_cells)
+{
+ static reg staticreg;
+ reg *r = &staticreg;
+
+ bzero((PCHAR) r, sizeof(reg));
+
+ if (buflen < addr_cells + size_cells) {
+ fatal("reg property smaller than #address-cell plus #size-cells\n");
+ }
+
+ r->lo = decode_int(buf + ((addr_cells-1) * 4));
+ r->hi = decode_int(buf);
+ r->size = decode_int(buf + ((addr_cells + size_cells - 1) * 4));
+
+ return (r);
+}
+
+reg *
+get_reg_prop(phandle node, char *key, int index)
+{
+ int res;
+ char *buf;
+ reg *regp;
+ int len = OFGetproplen(node, key);
+ int addr_cells, size_cells, offset;
+
+ buf = (char *)malloc(len);
+ res = OFGetprop(node, key, buf, len);
+ if (res != len) {
+ fatal("get_reg_prop(node %x, key '%s', len %x) returned %x\n",
+ node, key, len, res);
+ free(buf);
+ return ((reg *) 0);
+ }
+
+
+ addr_cells = get_int_prop(OFParent(node), "#address-cells");
+ if (addr_cells < 0) {
+ addr_cells = 2;
+ }
+ size_cells = get_int_prop(OFParent(node), "#size-cells");
+ if (size_cells < 0) {
+ size_cells = 1;
+ }
+
+ offset = index * (addr_cells + size_cells) * 4;
+ key = buf + offset;
+ len -= offset;
+ if (len) {
+ debug(VRDBG_TEST, "key %x len %x\n", key, len);
+ regp = decode_reg(key, len, addr_cells, size_cells);
+ } else {
+ debug(VRDBG_TEST, "returning NULL regp\n");
+ regp = NULL;
+ }
+
+ free(buf);
+ return (regp);
+}
+
+char *
+get_str_prop(phandle node, char *key, allocflag alloc)
+{
+ int len, res;
+ static char *priv_buf, priv_buf_len = 0;
+ char *cp;
+
+ len = OFGetproplen(node, key);
+ if (len == -1 || len == 0) {
+ return((char *) 0);
+ }
+
+ /*
+ * Leave room for a null terminator, on the off chance that the
+ * property isn't null-terminated.
+ */
+ len += 1;
+ if (alloc == ALLOC) {
+ cp = (char *) zalloc(len);
+ } else {
+ if (len > priv_buf_len) {
+ if (priv_buf_len) {
+ free(priv_buf);
+ }
+ priv_buf = (char *) zalloc(len);
+ priv_buf_len = len;
+ } else {
+ bzero(priv_buf, len);
+ }
+ cp = priv_buf;
+ }
+ len -= 1;
+
+ res = OFGetprop(node, key, cp, len);
+ if (res != len) {
+ fatal( "get_str_prop(node %x, key '%s', len %x) returned len %x\n",
+ node, key, len, res);
+ return((char *) 0);
+ }
+ return(cp);
+}
+
+int
+strcmp(const char *s, const char *t)
+{
+ int i;
+
+ for (i = 0; s[i] == t[i]; ++i) {
+ if (s[i] == '\0') {
+ return (0);
+ }
+ }
+ return((int) (s[i] - t[i]));
+}
+
+
+int
+strncmp(const char *s, const char *t, size_t len)
+{
+ int i;
+
+ for (i = 0; (s[i] == t[i]) && (i != (int) len); ++i) {
+ if (s[i] == '\0') {
+ return (0);
+ }
+ }
+ if (i == (int) len) {
+ return(0);
+ }
+ return((int) (s[i] - t[i]));
+}
+
+int
+strncasecmp(const char *s, const char *t, size_t len)
+{
+ int i;
+ char s1 = 0, t1 = 0;
+
+ for (i = 0; i != (int) len; ++i) {
+ if (s[i] == '\0') {
+ return (0);
+ }
+ s1 = s[i];
+ if (s1 >= 'a' && s1 <= 'z') {
+ s1 -= 0x20;
+ }
+ t1 = t[i];
+ if (t1 >= 'a' && t1 <= 'z') {
+ t1 -= 0x20;
+ }
+ if (s1 == t1) {
+ break;
+ }
+ }
+ if (i == (int) len) {
+ return(0);
+ }
+ return((int) (s1 - t1));
+}
+
+size_t
+strlen(const char *s)
+{
+ int i;
+
+ for (i = 0; s[i] != '\0'; ++i) {
+ ;
+ }
+ return((size_t) i);
+}
+
+char *
+strcpy(char *to, const char *from)
+{
+ int i = 0;
+
+ while (to[i] = from[i]) {
+ i += 1;
+ }
+ return(to);
+}
+
+char *
+strcat(char *to, const char *from)
+{
+ char *ret = to;
+
+ while (*to) {
+ to += 1;
+ }
+ strcpy(to, from);
+ return (ret);
+}
+
+VOID
+bcopy(char *from, char *to, int len)
+{
+ while (len--) {
+ *to++ = *from++;
+ }
+}
+
+VOID
+bzero(char *cp, int len)
+{
+ while (len--) {
+ *(cp + len) = 0;
+ }
+}
+
+VOID *
+zalloc(int size)
+{
+ VOID *vp;
+
+ vp = malloc(size);
+ bzero(vp, size);
+ return (vp);
+}
+
+VOID
+sleep(ULONG delay)
+{
+ delay += VrGetRelativeTime();
+ while (VrGetRelativeTime() < delay) {
+ ;
+ }
+}
+
+int
+claim(void *adr, int bytes)
+{
+ return(OFClaim((PCHAR) MAP(adr), bytes, 0));
+}
+
+VOID *
+alloc(int size, int align)
+{
+ return((VOID *) OFClaim(0, size, align));
+}
+
+int
+atoi(char *s)
+{
+ int temp = 0, base = 10;
+ char *start;
+
+ if (*s == '0') {
+ ++s;
+ if (*s == 'x') {
+ ++s;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+ start = s;
+again:
+ while (*s) {
+ switch (*s) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ temp = (temp * base) + (*s++ - '0');
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ if (base == 10) {
+ base = 16;
+ temp = 0;
+ s = start;
+ goto again;
+ }
+ temp = (temp * base) + (*s++ - 'a' + 10);
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ if (base == 10) {
+ base = 16;
+ temp = 0;
+ s = start;
+ goto again;
+ }
+ temp = (temp * base) + (*s++ - 'A' + 10);
+ break;
+ default:
+ return (temp);
+ }
+ }
+ return (temp);
+}
+
+char *
+index(char *s, int c)
+{
+ while (*s) {
+ if (*s == c) {
+ return (s);
+ }
+ ++s;
+ }
+ return ((char *) 0);
+}
+
+char *
+strcsep(char *s, const char sep)
+{
+ static char *saved_str = NULL;
+ char *temp;
+
+ if (s != NULL) {
+ saved_str = s;
+ }
+ if (saved_str == NULL) {
+ return(NULL);
+ }
+ s = index(saved_str, sep);
+ if (s != NULL) {
+ *s++ = '\0';
+ }
+ temp = saved_str;
+ saved_str = s;
+ return(temp);
+}
+
+char *
+strctok(char *s, const char sep)
+{
+ static char *saved_str = NULL;
+ char *temp;
+
+ if (s != NULL) {
+ saved_str = s;
+ }
+ if (saved_str == NULL) {
+ return(NULL);
+ }
+ s = index(saved_str, sep);
+ if (s != NULL) {
+ *s++ = '\0';
+ while (*s && (*s == sep)) {
+ ++s;
+ }
+ }
+ temp = saved_str;
+ saved_str = s;
+ return(temp);
+}
+
+char *
+capitalize(char *s)
+{
+ char *p;
+
+ p = s;
+ while (*p) {
+ *p = islower(*p) ? toupper(*p) : *p;
+ ++p;
+ }
+ return(s);
+}
+
+
+
+STATIC ihandle stdout = 0;
+STATIC char outbuf[128];
+STATIC int outbufc = 0;
+
+VOID
+putchar(char c)
+{
+ phandle ph;
+
+ if (stdout == 0) {
+ ph = OFFinddevice("/chosen");
+ if (ph == -1) {
+ /* What to do here?!? */
+ while (1) {
+ ;
+ }
+ }
+ stdout = get_int_prop(ph, "stdout");
+ }
+
+ if (c == '\n') {
+ outbuf[outbufc++] = '\r';
+ }
+ outbuf[outbufc++] = c;
+ if ((c == '\n') || (outbufc == 127)) {
+ OFWrite(stdout, outbuf, outbufc);
+ outbufc = 0;
+ return;
+ }
+}
+
+VOID
+puts(char *s)
+{
+ int count;
+
+ if (stdout == 0) {
+ putchar(*s++);
+ }
+ if (outbufc) {
+ OFWrite(stdout, outbuf, outbufc);
+ outbufc = 0;
+ }
+ if (count = strlen(s)) {
+ OFWrite(stdout, s, count);
+ }
+ putchar('\n');
+}
+
+STATIC ihandle stdin = 0;
+
+VOID
+gets(char *inbuf)
+{
+ int count;
+ phandle ph;
+
+ if (stdin == 0) {
+ ph = OFFinddevice("/chosen");
+ if (ph == -1) {
+ /* What to do here?!? */
+ while (1) {
+ ;
+ }
+ }
+ stdin = get_int_prop(ph, "stdin");
+ }
+
+ count = OFRead(stdin, inbuf, 127);
+ inbuf[count] = '\0';
+}
+
+#include <stdarg.h>
+
+VOID
+warn(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ doprnt(putchar, fmt, args);
+ va_end(args);
+}
+
+VOID
+fatal(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ doprnt(putchar, fmt, args);
+ OFExit();
+ va_end(args);
+}
+
+int level = 0;
+
+VOID
+debug(int debug_level, char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ if (!(debug_level & VrDebug)) {
+ return;
+ }
+ va_start(args, fmt);
+ for (i = 0; i < level; ++i) {
+ putchar('\t');
+ }
+ doprnt(putchar, fmt, args);
+ va_end(args);
+}
+
+STATIC char *sprintf_buf;
+
+STATIC VOID
+putbuf(char c)
+{
+ *sprintf_buf++ = c;
+}
+
+VOID
+sprintf(char *buf, char *fmt, ...)
+{
+ va_list args;
+
+ sprintf_buf = buf;
+ va_start(args, fmt);
+ doprnt(putbuf, fmt, args);
+ va_end(args);
+ putbuf('\0');
+}
+
+STATIC VOID
+doprnt(VOID (*func)(), char *fmt, va_list args)
+{
+ ULONG x;
+ LONG l;
+ char c, *s;
+
+ while (c = *fmt++) {
+ if (c != '%') {
+ func(c);
+ continue;
+ }
+ switch (c = *fmt++) {
+ case 'x':
+ x = va_arg(args, ULONG);
+ printbase(func, x, 16);
+ break;
+ case 'o':
+ x = va_arg(args, ULONG);
+ printbase(func, x, 8);
+ break;
+ case 'd':
+ l = va_arg(args, LONG);
+ if (l < 0) {
+ func('-');
+ l = -l;
+ }
+ printbase(func, (ULONG) l, 10);
+ break;
+ case 'c':
+ c = va_arg(args, char);
+ func(c);
+ break;
+ case 's':
+ s = va_arg(args, char *);
+ while (*s) {
+ func(*s++);
+ }
+ break;
+ default:
+ func(c);
+ break;
+ }
+ }
+}
+
+STATIC VOID
+printbase(VOID (*func)(), ULONG x, int base)
+{
+ static char itoa[] = "0123456789abcdef";
+ ULONG j;
+ char buf[16], *s = buf;
+
+ if (x == 0) {
+ func('0');
+ return;
+ }
+ bzero(buf, 16);
+ while (x) {
+ j = x % base;
+ *s++ = itoa[j];
+ x -= j;
+ x /= base;
+ }
+
+ for (--s; s >= buf; --s) {
+ func(*s);
+ }
+}
diff --git a/private/ntos/boot/veneer/vrload.c b/private/ntos/boot/veneer/vrload.c
new file mode 100644
index 000000000..9fdfc412d
--- /dev/null
+++ b/private/ntos/boot/veneer/vrload.c
@@ -0,0 +1,1035 @@
+/*
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirePower Systems Inc.
+ *
+ * $RCSfile: vrload.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/04/15 02:55:48 $
+ * $Locker: $
+ *
+ *
+ * Module Name:
+ * vrload.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 28-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added for DOS signature of PE in VrLoad();
+ * 18-Jul-94 Shin Iwamoto at FirePower Systems Inc.
+ * Created.
+ */
+
+
+#include "veneer.h"
+
+#define XXX_MAKE_DESCRIPTOR
+
+//
+// This must be defined in some header file. But for 3.5 it is not defined.
+//
+#define IMAGE_FILE_16BIT_MACHINE 0x0040
+
+
+typedef struct _VR_MEMORY_DESCRIPTOR {
+ struct _VR_MEMORY_DESCRIPTOR *NextEntry;
+ MEMORY_DESCRIPTOR MemoryEntry;
+} VR_MEMORY_DESCRIPTOR, *PVR_MEMORY_DESCRIPTOR;
+
+extern PVR_MEMORY_DESCRIPTOR VrMemoryListOrig;
+
+//
+// Some type definitions.
+//
+typedef struct _SECTION_RELOCATION_ENTRY {
+ ULONG FixupValue;
+ ULONG PointerToRelocations;
+ USHORT NumberOfRelocations;
+} SECTION_RELOCATION_ENTRY, *PSECTION_RELOCATION_ENTRY;
+
+//
+// Some definitions.
+//
+// These must be defined in veneer.h or ntimage.h?
+//
+#define HEADER_CHAR (IMAGE_FILE_EXECUTABLE_IMAGE | \
+ IMAGE_FILE_BYTES_REVERSED_LO | \
+ IMAGE_FILE_32BIT_MACHINE | \
+ IMAGE_FILE_BYTES_REVERSED_HI)
+#define HEADER_NOCHAR (IMAGE_FILE_16BIT_MACHINE | \
+ IMAGE_FILE_DLL)
+#define OPTIONAL_MAGIC_STD 0x010B
+
+//
+// Section numbers for local relocation entries
+//
+#define R_SN_TEXT 0
+#define R_SN_DATA 1
+#define R_SN_BSS 2
+#define R_SN_MAX 3
+
+
+#define MAX_ARGUMENT (512 - sizeof(ULONG) - 16*sizeof(PUCHAR))
+typedef struct _SAVED_ARGUMENTS {
+ ULONG Argc;
+ PUCHAR Argv[16];
+ UCHAR Arguments[MAX_ARGUMENT];
+} SAVED_ARGUMENTS, *PSAVED_ARGUMENTS;
+
+
+STATIC PSAVED_ARGUMENTS SavedArgs;
+STATIC ULONG VrActualBasePage;
+STATIC ULONG VrPageCount;
+
+
+//
+// Function declarations.
+//
+ARC_STATUS
+VrRelocateImage(
+ IN ULONG FileId,
+ IN PSECTION_RELOCATION_ENTRY RelocationTable,
+ IN ULONG NumberOfSections,
+ IN ULONG PointerToSymbolTable
+ );
+VOID
+VrCopyArguments(
+ IN ULONG Argc,
+ IN PCHAR Argv[]
+ );
+ARC_STATUS
+VrGenerateDescriptor(
+ IN PMEMORY_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount
+ );
+VOID
+VrResetMemory(
+ VOID
+ );
+VOID
+PxInvoke(
+ IN ULONG EntryAddress,
+ IN ULONG StackAddress,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ );
+VOID
+InsertMemDescriptor(
+ IN PVR_MEMORY_DESCRIPTOR MemDescriptor
+ );
+
+
+/*
+ * Name: VrLoad
+ *
+ * Description:
+ * This function reads a program into memory at a specified address
+ * an;d stores the execution address.
+ *
+ * Arguments:
+ * ImagePath - Supplies a pointer to the path of the file to load.
+ * TopAddress - Supplies the top address of a region of memory into
+ * which the file is to be loaded.
+ * EntryAddress- Supplies a pointer to a variable to receive the entry
+ * point of the image, if defined.
+ * LoaAddress - Supplies a pointer to a variable to receive the low address
+ * of the loaded file.
+ *
+ * Return Value:
+ * ESUCCESS is returned if the specified image file is loaded successfully.
+ * Otherwise, an unsuccessufl status is returned that describes the reason
+ * for failure.
+ *
+ */
+ARC_STATUS
+VrLoad(
+ IN PCHAR ImagePath,
+ IN ULONG TopAddress,
+ OUT PULONG EntryAddress,
+ OUT PULONG LowAddress
+ )
+{
+ PSECTION_RELOCATION_ENTRY RelocationTable;
+ IMAGE_DOS_HEADER DosHeader;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER OptionalHeader;
+ PIMAGE_SECTION_HEADER SectionHeader, SHeader;
+ ULONG FileId, NumberOfSections, Count;
+ ULONG ActualBase, ClaimSize, SectionOffset;
+ LARGE_INTEGER SeekPosition;
+ ARC_STATUS Status;
+ LONG NT_Signature;
+ LONG size, i;
+ PCHAR ReadAddr;
+ ULONG ReadSize;
+
+
+ debug(VRDBG_LOAD, "VrLoad: Entry - ImagePath: %s TopAddress: %x\n",
+ ImagePath, TopAddress);
+
+ //
+ // Attempt to open the load file.
+ //
+ if ((Status = VrOpen(ImagePath, ArcOpenReadOnly, &FileId)) != ESUCCESS) {
+ return Status;
+ }
+
+ //
+ // Read DOS Signature.
+ //
+ if ((Status = VrRead(FileId, &DosHeader, 2, &Count)) != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+
+ //
+ // If the file isn't a PE file including DOS header,
+ // it's probably a COFF file.
+ //
+ if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
+ bcopy((char *)&DosHeader, (char *)&FileHeader, 2);
+ ReadAddr = (PCHAR)&FileHeader + 2;
+ ReadSize = IMAGE_SIZEOF_FILE_HEADER - 2;
+ goto DirectCOFF;
+ }
+
+ //
+ // Read the remainder of DOS header.
+ //
+ if ((Status = VrRead(FileId, (PCHAR)&DosHeader+2, sizeof(DosHeader) - 2,
+ &Count)) != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+ if (Count != sizeof(DosHeader) - 2) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+ SeekPosition.HighPart = 0;
+ SeekPosition.LowPart = DosHeader.e_lfanew;
+ if (Status = VrSeek(FileId, &SeekPosition, SeekAbsolute)) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+
+ //
+ // Read NT Signature and confirm it.
+ //
+ if ((Status = VrRead(FileId, &NT_Signature, sizeof(NT_Signature), &Count))
+ != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+ if (Count != sizeof(NT_Signature) || NT_Signature != IMAGE_NT_SIGNATURE) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+
+ ReadAddr = (PCHAR)&FileHeader;
+ ReadSize = IMAGE_SIZEOF_FILE_HEADER;
+
+ DirectCOFF:
+ //
+ // Read the image header from the file.
+ //
+ if ((Status = VrRead(FileId, ReadAddr, ReadSize, &Count)) != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+ if (Count != ReadSize) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+
+ //
+ // Check the header.
+ //
+ if ((FileHeader.Machine != IMAGE_FILE_MACHINE_POWERPC) ||
+ ((FileHeader.Characteristics & HEADER_CHAR) != HEADER_CHAR) ||
+ ((FileHeader.Characteristics & HEADER_NOCHAR) != 0) ) {
+
+ (VOID)VrClose(FileId);
+ return ENOEXEC;
+ }
+
+ //
+ // Read the optional header.
+ //
+ if ((Status = VrRead(FileId, &OptionalHeader,
+ FileHeader.SizeOfOptionalHeader, &Count)) != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+ if (Count != FileHeader.SizeOfOptionalHeader) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+
+ //
+ // More check with the optional header.
+ //
+ if (OptionalHeader.Magic != OPTIONAL_MAGIC_STD) {
+ (VOID)VrClose(FileId);
+ return ENOEXEC;
+ }
+
+ //
+ // If the image cannot be relocated, set the ActualBase to the code
+ // base, and compute the image size by subtracting the code base from
+ // the data base plus the data size. If the image can be relocated,
+ // set ActualBase to the TopAddress minus the image size, compute
+ // image size by adding the code size, initialized data, and
+ // uninitialized data.
+ //
+ if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) {
+ ActualBase = OptionalHeader.BaseOfCode;
+ ClaimSize = OptionalHeader.BaseOfData +
+ OptionalHeader.SizeOfInitializedData - ActualBase;
+ } else {
+ ClaimSize = OptionalHeader.SizeOfCode +
+ OptionalHeader.SizeOfInitializedData +
+ OptionalHeader.SizeOfUninitializedData;
+ // ActualBase = OptionalHeader.ImageBase;
+#ifdef XXX_I_KNOW_PE
+ ActualBase = (TopAddress - ClaimSize) & ~(PAGE_SIZE - 1);
+#else
+ ActualBase = OptionalHeader.ImageBase;
+ ActualBase &= 0x7fffffff;
+#endif XXX_I_KNOW_PE
+ }
+
+ //
+ // Allocate and read the section headers.
+ //
+ size = FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
+ SectionHeader = (PIMAGE_SECTION_HEADER)malloc(size);
+ if ((Status = VrRead(FileId, (PCHAR)SectionHeader, size, &Count))
+ != ESUCCESS) {
+ (VOID)VrClose(FileId);
+ return Status;
+ }
+ if (Count != (ULONG) size) {
+ (VOID)VrClose(FileId);
+ return EBADF; // XXXX
+ }
+
+ //
+ //
+ //
+ NumberOfSections = FileHeader.NumberOfSections;
+ if (strcmp((PCHAR)(SectionHeader[NumberOfSections-1].Name), ".debug")
+ == 0) {
+ NumberOfSections--;
+ ClaimSize -= SectionHeader[NumberOfSections].SizeOfRawData;
+ }
+
+ //
+ // Allocate the relocation table.
+ //
+ size = NumberOfSections * sizeof(SECTION_RELOCATION_ENTRY);
+ RelocationTable = (PSECTION_RELOCATION_ENTRY) malloc(size);
+
+ //
+ // Zero the relocation table.
+ //
+ bzero((char *)RelocationTable, size);
+
+ //
+ // Convert ClaimSize to be page-aligned.
+ //
+ ClaimSize = (ClaimSize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+
+ //
+ // Convert ActualBase and ClaimSize to be in units of pages instead of
+ // bytes. This is the interface between VrExecute and VrLoad.
+ //
+ VrActualBasePage = (ActualBase & 0x7fffffff) >> PAGE_SHIFT;
+ VrPageCount = ClaimSize >> PAGE_SHIFT;
+
+ //
+ // Claim memory at specified virtual address
+ //
+ if (claim((void *)ActualBase, ClaimSize) == -1) {
+ fatal("Veneer: Couldn't claim %x bytes of VM at %x\n",
+ ClaimSize, ActualBase);
+ }
+
+ //
+ // Set output parametes.
+ //
+ *LowAddress = ActualBase;
+#ifdef XXX_I_KNOW_PE
+ *EntryAddress = ActualBase
+ + (OptionalHeader.AddressOfEntryPoint - OptionalHeader.BaseOfCode);
+#else
+ *EntryAddress = ActualBase + OptionalHeader.AddressOfEntryPoint;
+#endif XXX_I_KNOW_PE
+
+ //
+ // Scan through the sections and either read them into memory or
+ // clear the memory as appropriate.
+ //
+ SectionOffset = 0;
+ for (i = 0, SHeader = SectionHeader; (ULONG) i < NumberOfSections;
+ i++, SHeader++) {
+ ULONG SectionBase;
+
+ if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) {
+ SectionBase = SHeader->VirtualAddress;
+ } else {
+#ifdef XXX_I_KNOW_PE
+ SectionBase = ActualBase + SectionOffset;
+#else
+ SectionBase = ActualBase + SHeader->VirtualAddress;
+#endif XXX_I_KNOW_PE
+
+ (RelocationTable+i)->PointerToRelocations =
+ SHeader->PointerToRelocations;
+ (RelocationTable+i)->NumberOfRelocations =
+ SHeader->NumberOfRelocations;
+ (RelocationTable+i)->FixupValue =
+ SectionBase - SHeader->VirtualAddress;
+ }
+
+ //
+ // If the section is code or initialized data, then read
+ // the code or data into memory.
+ //
+ if ((SHeader->Characteristics & ( IMAGE_SCN_CNT_CODE |
+ IMAGE_SCN_CNT_INITIALIZED_DATA) ) != 0) {
+ SeekPosition.LowPart = SHeader->PointerToRawData;
+ SeekPosition.HighPart = 0;
+ if ((Status = VrSeek(FileId, &SeekPosition, SeekAbsolute))
+ != ESUCCESS) {
+ break;
+ }
+ if ((Status = VrRead(FileId, (PVOID)SectionBase,
+ SHeader->SizeOfRawData, &Count)) != ESUCCESS) {
+ break;
+ }
+ if (Count != SHeader->SizeOfRawData) {
+ Status = EBADF; // XXXX
+ break;
+ }
+
+ //
+ // Set the offset of the next section.
+ //
+ SectionOffset += SHeader->SizeOfRawData;
+ } else
+ if ((SHeader->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ != 0) {
+ bzero((PVOID)SectionBase, SHeader->SizeOfRawData);
+
+ //
+ // Set the offset of the next section.
+ //
+ SectionOffset += SHeader->SizeOfRawData;
+ }
+ }
+
+ //
+ // If code has to be relocated, do so.
+ //
+ if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) == 0) {
+ if (ActualBase != OptionalHeader.ImageBase) {
+ Status = VrRelocateImage( FileId, RelocationTable,
+ NumberOfSections,
+ FileHeader.PointerToSymbolTable);
+ }
+ }
+
+ //
+ // Deallocate allocated area and close the file.
+ //
+ free((char*) SectionHeader);
+ free((char*) RelocationTable);
+ (VOID)VrClose(FileId);
+
+ debug(VRDBG_LOAD, "VrLoad: Exit - EntryAddress: %x LowAddress: %x Status:%d\n",
+ *EntryAddress, *LowAddress, Status);
+
+ return Status;
+}
+
+
+
+/*
+ * Name: VrInvoke
+ *
+ * Description:
+ * This function invokes a previously loaded program.
+ *
+ * Arguments:
+ * EntryAddress- Supplies the execution address of the program to be loaded.
+ * StackAddress- Supplies the stack address that is used to reset the stack
+ * pointer before the program is invoked.
+ * Argc - Supplies the argument count for the program.
+ * Argv - Supplies a pointer to the argument list for the program.
+ * Envp - Supplies a pointer to the environment for the program.
+ *
+ * Return Value:
+ * ESUCCESS is returned if the address is invalid.
+ * EFAULT indicates an invalid address.
+ *
+ */
+ARC_STATUS
+VrInvoke(
+ IN ULONG EntryAddress,
+ IN ULONG StackAddress,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ )
+{
+ //
+ // Check for aligend address.
+ //
+ if ((EntryAddress & 0x3) == 0 && (StackAddress & 0x3) == 0) {
+#ifdef notdef
+ free(VrDescriptorMemory);
+ VrMemoryListOrig = (PVR_MEMORY_DESCRIPTOR)NULL;
+#endif // notdef
+
+ PxInvoke(EntryAddress, StackAddress, Argc, Argv, Envp);
+ } else {
+ return EFAULT;
+ }
+
+ return ESUCCESS;
+}
+
+
+
+/*
+ * Name: VrExecute
+ *
+ * Description:
+ * This function reads the program specified by ImagePath into memory
+ * and then starts the program. If the loaded program returns, then
+ * control returns to the platform firmware, not to the caller.
+ *
+ * Arguments:
+ * ImagePath - Supplies a pointer to the pathname of the program
+ * to be loaded.
+ * Argc - Supplies the argument count for the program.
+ * Argv - Supplies a pointer to the argument list for the program.
+ * Envp - Supplies a pointer to the environment for the program.
+ *
+ * Return Value:
+ * ESUCCESS is returned if the address is invalid.
+ * EFAULT indicates an invalid address.
+ *
+ */
+ARC_STATUS
+VrExecute(
+ IN PCHAR ImagePath,
+ IN ULONG Argc,
+ IN PCHAR Argv[],
+ IN PCHAR Envp[]
+ )
+{
+ ARC_STATUS Status;
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ ULONG BottomAddress;
+ CHAR TempPath[256];
+ PULONG TransferRoutine;
+
+ if (strlen(ImagePath) >= sizeof(TempPath)) {
+ return ENAMETOOLONG;
+ }
+
+ //
+ // Copy the Arguments to a safe place as they can be in the running
+ // program space which can be overwritten by the program about
+ // to be loaded.
+ //
+ (VOID)VrCopyArguments(Argc, Argv);
+ strcpy(TempPath, ImagePath);
+
+ //
+ // Reinitialize the memory descriptors
+ //
+ VrResetMemory();
+
+ //
+ // Look for a piece of free memory.
+ //
+ MemoryDescriptor = VrGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL ) {
+
+ //
+ // If the memory is at least 4 megabytes and is free attempt to
+ // load the program.
+ //
+ if ((MemoryDescriptor->MemoryType == MemoryFree)
+ && (MemoryDescriptor->PageCount >= 1024)) {
+
+ //
+ // Set the top address to the top of the descriptor.
+ //
+ Status = VrLoad(TempPath,
+ ((MemoryDescriptor->BasePage + MemoryDescriptor->PageCount)
+ << PAGE_SHIFT),
+ (PULONG)&TransferRoutine,
+ &BottomAddress);
+
+ if (Status == ESUCCESS) {
+
+ //
+ // Find the actual area of memory that was used, and generate
+ // a descriptor for it. Also, claim the according memory
+ // from OpenFirmware.
+ //
+#ifdef XXX_MAKE_DESCRIPTOR
+ MemoryDescriptor = VrGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL) {
+ if ((MemoryDescriptor->MemoryType == MemoryFree)
+ && (VrActualBasePage >= MemoryDescriptor->BasePage)
+ && ((VrActualBasePage + VrPageCount) <=
+ (MemoryDescriptor->BasePage
+ + MemoryDescriptor->PageCount)) ) {
+ break;
+ }
+ MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor);
+ }
+ if (MemoryDescriptor != NULL) {
+ Status = VrGenerateDescriptor(MemoryDescriptor,
+#ifdef EXEC_MEM_TO_LOADED
+ MemoryLoadedProgram,
+#else
+ MemoryFirmwareTemporary,
+#endif // EXEC_MEM_TO_LOADED
+ VrActualBasePage,
+ VrPageCount);
+ if (Status != ESUCCESS) {
+ return Status;
+ }
+#endif // XXX_MAKE_DESCRIPTOR
+
+
+ Status = VrInvoke((ULONG)TransferRoutine,
+ BottomAddress,
+ SavedArgs->Argc,
+ SavedArgs->Argv,
+ Envp );
+#ifdef EXEC_MEM_TO_LOADED
+#else
+ MemoryDescriptor->MemoryType = MemoryLoadedProgram;
+#endif // EXEC_MEM_TO_LOADED
+ return Status;
+
+#ifdef XXX_MAKE_DESCRIPTOR
+ }
+#endif // XXX_MAKE_DESCRIPTOR
+ }
+ if (Status != ENOMEM) {
+ return Status;
+ }
+ }
+
+ MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ return ENOMEM;
+}
+
+
+/*
+ * Name: VrLoadInitialize
+ *
+ * Description:
+ * This routine initializes the firmware load services.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrLoadInitialize(
+ VOID
+ )
+{
+ debug(VRDBG_ENTRY, "VrLoadInitialize BEGIN....\n");
+ (PARC_LOAD_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[LoadRoutine] = VrLoad;
+
+ (PARC_INVOKE_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[InvokeRoutine] = VrInvoke;
+
+ (PARC_EXECUTE_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[ExecuteRoutine] = VrExecute;
+
+ SavedArgs = new(SAVED_ARGUMENTS);
+ debug(VRDBG_ENTRY, "VrLoadInitialize ....END\n");
+}
+
+
+/*
+ * Name: VrRelocateImage
+ *
+ * Description:
+ * This function relocates an image file that was not loaded into memory
+ * at the prefered address.
+ *
+ * Arguments:
+ * FileId - Supplies the file identifier for the image file.
+ * RelocationTable
+ * - Supplies a pointer to a table of section relocation info.
+ *
+ * Return Value:
+ * ESUCCESS is returned in the scan if\s successful. Otherwise, return
+ * an unsuccessful status.
+ *
+ */
+STATIC
+ARC_STATUS
+VrRelocateImage(
+ IN ULONG FileId,
+ IN PSECTION_RELOCATION_ENTRY RelocationTable,
+ IN ULONG NumberOfSections,
+ IN ULONG PointerToSymbolTable
+ )
+{
+ IMAGE_RELOCATION RelocationEntry;
+ IMAGE_SYMBOL ImageSymbol;
+ LARGE_INTEGER SeekPosition;
+ ULONG Section, Index, Count, Offset;
+ PULONG FixupAddress;
+ ARC_STATUS Status;
+
+ //
+ // Read the relocation table for each section.
+ //
+ for (Section = 0; Section < NumberOfSections; Section++) {
+ for (Index = 0; Index < RelocationTable[Section].NumberOfRelocations;
+ Index++) {
+ if (Index == 0) {
+ SeekPosition.LowPart =
+ RelocationTable[Section].PointerToRelocations;
+ SeekPosition.HighPart = 0;
+ if ((Status = VrSeek(FileId, &SeekPosition, SeekAbsolute))
+ != ESUCCESS) {
+ return Status;
+ }
+ }
+ if ((Status = VrRead(FileId, (PCHAR)&RelocationEntry,
+ sizeof(RelocationEntry), &Count)) != ESUCCESS) {
+ return Status;
+ }
+ if (Count != sizeof(RelocationEntry)) {
+ return EBADF;
+ }
+
+ //
+ // Get the address for the fixup.
+ //
+ FixupAddress = (PULONG)RelocationEntry.VirtualAddress
+ + RelocationTable[Section].FixupValue;
+
+ //
+ // Read the symbol table.
+ //
+ SeekPosition.LowPart = PointerToSymbolTable
+ + RelocationEntry.SymbolTableIndex * sizeof(IMAGE_SYMBOL);
+ if ((Status = VrRead(FileId, (PCHAR)&ImageSymbol,
+ sizeof(ImageSymbol), &Count)) != ESUCCESS) {
+ return Status;
+ }
+ if (Count != sizeof(ImageSymbol)) {
+ return EBADF;
+ }
+
+ //
+ // Apply the fixup.
+ //
+ if (ImageSymbol.StorageClass != IMAGE_SYM_CLASS_EXTERNAL) {
+ Offset = RelocationTable[ImageSymbol.SectionNumber].FixupValue;
+ } else {
+ Offset = 0;
+ }
+
+ switch (RelocationEntry.Type) {
+
+ //
+ // Absolute - no fixup required.
+ //
+ case IMAGE_REL_PPC_ABSOLUTE:
+ break;
+
+ //
+ // 32-bit address - relocate the entire address.
+ //
+ case IMAGE_REL_PPC_ADDR32:
+ *FixupAddress += (ULONG)Offset;
+ break;
+
+ //
+ // 26-bit address, 26-bit PC-relative offset
+ //
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_REL24:
+ *FixupAddress = ((*FixupAddress) & 0xfc000003) +
+ ((*FixupAddress) & 0x03fffffc + (Offset << 2)) & 0x03fffffc;
+ break;
+
+ //
+ // 16-bit address, 16-bit offset from TOC base
+ //
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_TOCREL16:
+ *FixupAddress = ((*FixupAddress) & 0xffff0000) +
+ ((*FixupAddress) & 0x0000ffff + Offset) & 0x0000ffff;
+ break;
+
+ //
+ // 14-bit address, 14-bit PC-relative offset,
+ // 14-bit offset from TOC base
+ //
+ case IMAGE_REL_PPC_ADDR14:
+ case IMAGE_REL_PPC_REL14:
+ case IMAGE_REL_PPC_TOCREL14:
+ *FixupAddress = ((*FixupAddress) & 0xffff0003) +
+ ((*FixupAddress) & 0x0000fffc + (Offset << 2)) & 0x0000fffc;
+ break;
+
+ default:
+ fatal("Veneer: unknown relocation type %d\n",
+ RelocationEntry.Type);
+ }
+ }
+ }
+
+ return ESUCCESS;
+}
+
+
+/*
+ * Name: VrCopyArguments
+ *
+ * Description:
+ * This routine copies the supplied arguments into the Veneer space.
+ *
+ * Arguments:
+ * Argc, Argv - Supply the arguments to be copied.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+STATIC VOID
+VrCopyArguments(
+ IN ULONG Argc,
+ IN PCHAR Argv[]
+ )
+{
+ PUCHAR Source, Destination;
+ ULONG Index;
+
+ SavedArgs->Argc = Argc;
+ Destination = &SavedArgs->Arguments[0];
+ for (Index = 0; Index < Argc; Index++) {
+ Source = Argv[Index];
+ SavedArgs->Argv[Index] = Destination;
+ while (*Destination++ = *Source++) ;
+ }
+}
+
+
+/*
+ * Name: VrResetMemory
+ *
+ * Description:
+ * This loops through and clears all of the appropriate memory,
+ * releasing the memory to OpenFirmware, and then calls VrCreateMemory
+ * to reset the memory descriptors.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrResetMemory(
+ VOID
+ )
+{
+ PMEMORY_DESCRIPTOR MemoryDescriptor;
+ PVR_MEMORY_DESCRIPTOR CurDesc, FreeDesc;
+
+ //
+ // Release all memory not used by the firmware.
+ //
+ MemoryDescriptor = VrGetMemoryDescriptor(NULL);
+ while (MemoryDescriptor != NULL) {
+
+#ifdef notdef
+ DisplayMemoryDescriptor(MemoryDescriptor);
+#endif // notdef
+
+ if ((MemoryDescriptor->MemoryType == MemoryLoadedProgram) ||
+ (MemoryDescriptor->MemoryType == MemoryFreeContiguous)) {
+
+ bzero((PVOID) (MemoryDescriptor->BasePage << PAGE_SHIFT),
+ (MemoryDescriptor->PageCount << PAGE_SHIFT));
+
+ OFRelease((PVOID)(MemoryDescriptor->BasePage << PAGE_SHIFT),
+ (MemoryDescriptor->PageCount << PAGE_SHIFT));
+ }
+
+ MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor);
+ }
+
+ CurDesc = VrMemoryListOrig;
+ while(CurDesc != NULL) {
+ FreeDesc = CurDesc;
+ CurDesc = CurDesc->NextEntry;
+ free((char*)FreeDesc);
+ }
+ VrMemoryListOrig = (PVR_MEMORY_DESCRIPTOR) NULL;
+ VrCreateMemoryDescriptors();
+}
+
+
+/*
+ * Name: VrGenerateDescriptor
+ *
+ * Description:
+ * This routine allocates a new memory descriptor to describe the
+ * specified region of memory.
+ *
+ * Arguments:
+ * MemoryDescriptor - Supplies a pointer to a free memory descriptor
+ * from which the specified memory is to be allocated.
+ * MemoryType - Supplies the type that is assigned to the allocated
+ * memory.
+ * BasePage - Supplies the base page number.
+ * PageCount - Supplies the number of pages.
+ *
+ * Return Value:
+ *
+ */
+ARC_STATUS
+VrGenerateDescriptor(
+ IN PMEMORY_DESCRIPTOR MemoryDescriptor,
+ IN MEMORY_TYPE MemoryType,
+ IN ULONG BasePage,
+ IN ULONG PageCount
+ )
+{
+ PVR_MEMORY_DESCRIPTOR MemDescriptor, NewDescriptor;
+ ULONG Offset;
+
+
+ MemDescriptor = (PVR_MEMORY_DESCRIPTOR) MemoryDescriptor;
+
+ //
+ // Claim the memory from OpenFirmware.
+ //
+ if ((claim((void *)(BasePage << PAGE_SHIFT), PageCount << PAGE_SHIFT))
+ == -1) {
+ return ENOMEM;
+ }
+
+ //
+ // If the specified region totally consumes the free region, then no
+ // additional descriptors need to be allocated. If the specified region
+ // is at the start or end of the free region, then only one descriptor
+ // needs to be allocated. Otherwise, two additional descriptors need to
+ // be allocated.
+ //
+ Offset = BasePage - MemDescriptor->MemoryEntry.BasePage;
+ if ((Offset == 0) && (PageCount == MemDescriptor->MemoryEntry.PageCount)) {
+
+ //
+ // The specified region totally consumes the free region.
+ //
+ MemDescriptor->MemoryEntry.MemoryType = MemoryType;
+
+ } else {
+
+ //
+ // A memory descriptor must be generated to describe the allocated
+ // memory.
+ //
+ NewDescriptor = new(VR_MEMORY_DESCRIPTOR);
+ NewDescriptor->MemoryEntry.MemoryType = MemoryType;
+ NewDescriptor->MemoryEntry.BasePage = BasePage;
+ NewDescriptor->MemoryEntry.PageCount = PageCount;
+
+ //
+ // Insert Memory Descriptor List.
+ //
+ InsertMemDescriptor(NewDescriptor);
+
+ //
+ // Determine whether an additional memory descriptor must be generated.
+ //
+ if (BasePage == MemDescriptor->MemoryEntry.BasePage) {
+ MemDescriptor->MemoryEntry.BasePage += PageCount;
+ MemDescriptor->MemoryEntry.PageCount -= PageCount;
+ } else {
+ if ((Offset + PageCount) == (MemDescriptor->MemoryEntry.BasePage +
+ MemDescriptor->MemoryEntry.PageCount)) {
+
+ //
+ // The specified region lies at the end of the free region.
+ //
+ MemDescriptor->MemoryEntry.PageCount -= PageCount;
+
+ } else {
+
+ //
+ // The specified region lies in the middle of the free region.
+ // Another memory descriptor must be generated.
+ //
+ NewDescriptor = new(VR_MEMORY_DESCRIPTOR);
+ NewDescriptor->MemoryEntry.MemoryType = MemoryFree;
+ NewDescriptor->MemoryEntry.BasePage = BasePage + PageCount;
+ NewDescriptor->MemoryEntry.PageCount =
+ MemDescriptor->MemoryEntry.PageCount - PageCount - Offset;
+
+ //
+ // Insert Memory Descriptor List.
+ //
+ InsertMemDescriptor(NewDescriptor);
+
+
+ MemDescriptor->MemoryEntry.PageCount = Offset;
+ }
+ }
+ }
+
+ return ESUCCESS;
+}
+
+
+VOID
+InsertMemDescriptor(
+ IN PVR_MEMORY_DESCRIPTOR MemDescriptor
+ )
+{
+ PVR_MEMORY_DESCRIPTOR Entry;
+
+ for (Entry = VrMemoryListOrig; Entry; Entry = Entry->NextEntry) {
+ if ((Entry->MemoryEntry.BasePage < MemDescriptor->MemoryEntry.BasePage)
+ && ((Entry->NextEntry == NULL) ||
+ (Entry->NextEntry->MemoryEntry.BasePage >
+ MemDescriptor->MemoryEntry.BasePage))) {
+
+ MemDescriptor->NextEntry = Entry->NextEntry;
+ Entry->NextEntry = MemDescriptor;
+ break;
+ }
+ }
+}
diff --git a/private/ntos/boot/veneer/vrmain.c b/private/ntos/boot/veneer/vrmain.c
new file mode 100644
index 000000000..a90970420
--- /dev/null
+++ b/private/ntos/boot/veneer/vrmain.c
@@ -0,0 +1,1314 @@
+/*
+ * Copyright (c) 1994, 1996 FirePower Systems, Inc.
+ * Copyright 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrmain.c $
+ * $Revision: 1.41 $
+ * $Date: 1996/06/25 03:02:44 $
+ * $Locker: $
+ *
+ *
+ *
+ *
+ *
+ * HISTORY
+ * 09-21-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added some information in the system parameter block,
+ * such as signature.
+ * 07-21-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added calling VrEnvInitialize() and VrMemoryInitialize()
+ * in VrInitSystem().
+ * 07-20-94 Shin Iwamoto at FirePower Systems Inc.
+ * Moved here from VrInitSystem() and VrNotYet() originally
+ * in vrconfig.c.
+ *
+ */
+
+
+#include "veneer.h"
+
+
+int VrDebug = 0;
+BOOLEAN use_bat_mapping;
+
+/*
+ * Bootdev is either specified in the command line or if not is the device
+ * whence you booted.
+ * See create_argv() below for the magic used to fill in XYZZY.
+ */
+char *Bootpath = 0;
+char *Osloader = 0;
+char *SystemPath = 0;
+
+#define STR_XYZZY "xyzzy"
+#define STR_OSLOADER "\\os\\winnt\\osloader.exe"
+#define STR_OSLOADFN "\\WINNT"
+#define STR_OSLOADPART STR_XYZZY
+#define STR_LDIDENT "Windows NT 3.5"
+#define STR_FWSEARCH STR_XYZZY
+#define STR_FWTEST STR_XYZZY
+
+#define MAX_ARGC 16
+#define MAX_ENVC 16
+char *VrArgv[MAX_ARGC], *VrEnvp[MAX_ENVC];
+int VrArgc, VrEnvc;
+
+#define NEITHER 0
+#define ARGVONLY 1
+#define ENVONLY 2
+#define BOTH 3
+
+struct argv_tab {
+ char *key;
+ char *val;
+ int which;
+
+} argv_tab[MAX_ARGC] = {
+ { "OsLoader", STR_OSLOADER, BOTH },
+ { "SystemPartition", STR_XYZZY, BOTH },
+ { "OSLoadFilename", STR_OSLOADFN, BOTH },
+ { "OSLoadPartition", STR_OSLOADPART, BOTH },
+ { "OSLoadOptions", "nodebug", BOTH },
+ { "LoadIdentifier", STR_LDIDENT, BOTH },
+ { "AutoLoad", "yes", ENVONLY },
+ { "FWSearchPath", STR_FWSEARCH, ENVONLY },
+ { "LastKnownGood", "False", ENVONLY },
+ { "FWTEST", STR_FWTEST, ENVONLY }
+};
+
+STATIC VOID parse_args(VOID);
+STATIC VOID find_boot_dev(VOID);
+STATIC VOID collect_argv(VOID);
+STATIC VOID create_argv(VOID);
+STATIC VOID update_argv(char *, char *);
+STATIC VOID add_argv(char *, char *);
+STATIC VOID read_ARC_env_vars(VOID);
+STATIC VOID add_envp(char *, char *);
+STATIC VOID VrInitSystem (VOID);
+STATIC VOID VrInitSystemBlock (VOID);
+STATIC VOID VrNotYet(VOID);
+STATIC VOID VrKseg0(VOID);
+STATIC VOID move_amd_to_isa_hack(VOID);
+STATIC VOID move_ide_to_isa_hack(VOID);
+STATIC VOID move_scsi_children_to_ide_hack(VOID);
+STATIC VOID move_multi_to_root(PCONFIGURATION_NODE);
+STATIC CHAR *choose_args( char *, char *, int);
+PCHAR VrCanonicalName( IN PCHAR Variable);
+
+/* LONG claimreal(PVOID, ULONG); */
+STATIC LONG claimphys(PVOID, ULONG, ULONG);
+STATIC LONG map(PVOID, PVOID, ULONG, ULONG);
+STATIC VOID check_mmu_type (VOID);
+extern ULONG VrGetProcRev();
+
+typedef VOID (*VR_NOT_YET_ROUTINE) (VOID);
+
+main(VOID *resid, VOID *entry, int (cif_handler)(long *))
+{
+ ihandle bootih;
+ ULONG FileId;
+ ARC_STATUS res;
+ void (*jump_osloader)(int, char **, char**);
+ extern VOID Salutation();
+
+ Salutation();
+
+ VrInitSystemBlock();
+
+ check_mmu_type();
+
+ read_ARC_env_vars();
+
+ /*
+ * Do something with the arg string.
+ */
+ parse_args();
+
+ //
+ // Set up the "kseg0" translation.
+ //
+ VrKseg0();
+
+ //
+ // Build the device tree.
+ //
+ debug(VRDBG_MAIN, "Building the device tree...\n");
+ walk_obp((phandle) 0,
+ (PCONFIGURATION_NODE) 0,
+ (PCONFIGURATION_NODE) 0,
+ (PCONFIGURATION_NODE) 0
+ );
+
+ //
+ // Move all MultiFunction adapters (usually PCI or ISA,
+ // presumably) to be children of the System Class (i.e., RootNode).
+ // This is because the NT kernel prefers to limit the complexity
+ // of nested bus nodes.
+ //
+
+ debug(VRDBG_MAIN, "main: move all multi nodes to children of root...\n");
+ move_multi_to_root(RootNode);
+
+ debug(VRDBG_MAIN, "main: AMD nodes become children of isa...\n");
+ move_amd_to_isa_hack();
+
+ debug(VRDBG_MAIN, "Done with the device tree.\n");
+ if (VrDebug & VRDBG_DUMP) {
+ dump_tree(RootNode);
+ sleep(10);
+ } else if (VrDebug & VRDBG_CONFIG) {
+ quick_dump_tree(RootNode);
+ sleep(10);
+ }
+
+ //
+ // Build the system parameter block.
+ //
+ debug(VRDBG_MAIN, "main: Build the system parameter block...\n");
+ VrInitSystem();
+
+ //
+ // Determine the boot path and translate it to ARC form.
+ //
+ debug(VRDBG_MAIN, "main: find boot device...\n");
+ find_boot_dev();
+ debug(VRDBG_MAIN, "main: create argument and environment lists...\n");
+ create_argv();
+ warn("Booting from '%s'\n", VrArgv[0]);
+
+ res = VrOpen(VrArgv[0], ArcOpenReadOnly, &FileId);
+ if (res != ESUCCESS) {
+ fatal("VrOpen returned %x\n", res);
+ }
+
+ debug(VRDBG_MAIN, "main: setup boot ihandle, jump_osloader handle...\n");
+ bootih = FileTable[FileId].IHandle;
+ jump_osloader = load_file(bootih);
+ VrClose(FileId);
+ VrFlushAllCaches();
+
+ debug(VRDBG_MAIN, "main: create memory descriptor list...\n");
+ VrCreateMemoryDescriptors();
+ if (VrDebug & VRDBG_MEM) {
+ DisplayMemory();
+ }
+
+ if (VrDebug & VRDBG_HOLDIT) {
+
+ warn("Jumping to 0x%x\n", (char *)jump_osloader);
+ puts("This time for sure!");
+ OFEnter();
+ } else {
+ puts("\233H\233J"); // Clear screen
+ }
+ debug(VRDBG_MAIN, "main: launch OSLOADER!!! ...\n");
+ jump_osloader(VrArgc, VrArgv, VrEnvp);
+ OFExit();
+ return (0);
+}
+
+STATIC VOID
+check_mmu_type(VOID)
+{
+ ihandle ih;
+
+ ih = get_int_prop (OFFinddevice("/chosen"), "cpu");
+ if (ih == -1) {
+ use_bat_mapping = TRUE;
+ } else {
+ use_bat_mapping =
+ (OFGetproplen(OFInstanceToPackage(ih),"603-translation") == -1);
+ }
+}
+
+#define NEXT_TOKEN() if ((bootargs = strctok(NULL, ' ')) == NULL) return;
+
+STATIC VOID
+parse_args(VOID)
+{
+ phandle ph;
+ char *bootargs;
+ char *key, *val;
+ struct argv_tab *atp = argv_tab;
+
+ ph = OFFinddevice("/chosen");
+ if (ph == 0) {
+ warn("parse_args: No phandle for '/chosen'\n");
+ return;
+ }
+
+ debug(VRDBG_MAIN, "parse_args: /chosen phandle %x\n", ph);
+ bootargs = get_str_prop(ph, "bootargs", ALLOC);
+ if (bootargs == NULL || *bootargs == '\0') {
+ return;
+ }
+ debug(VRDBG_MAIN, "bootargs: '%s'\n", bootargs);
+
+ bootargs = strctok(bootargs, ' ');
+ if (bootargs[0] != '-') {
+
+ debug(VRDBG_MAIN, "Boot file '%s'\n", bootargs);
+ if (bootargs[0] == '\\') {
+
+ //
+ // We're just specifying the file to boot:
+ // update the OsLoader argument but nothing else.
+ //
+ update_argv("OsLoader", bootargs);
+
+ } else {
+
+ //
+ // Without a leading backslash, bootargs presumably
+ // contains a full device path.
+ // If so, update both Bootpath and OsLoader.
+ //
+ Bootpath = bootargs;
+ if (key = index(Bootpath, '\\')) {
+ val = (char *) malloc(strlen(key)+1);
+ strcpy(val, key);
+ update_argv("OsLoader", val);
+ *key = '\0';
+ }
+ }
+
+ debug(VRDBG_MAIN, "Bootpath '%s'\n", Bootpath);
+ for ( ; atp->key != NULL; ++atp) {
+ if (strcmp("OsLoader", atp->key) == 0) {
+ debug(VRDBG_MAIN, "OsLoader '%s'\n", atp->val);
+ break;
+ }
+ }
+ NEXT_TOKEN();
+ }
+
+ while (bootargs && (*bootargs != '\0')) {
+ if (strncmp(bootargs, "-vrdebug", 8) == 0) {
+ NEXT_TOKEN();
+ debug(VRDBG_MAIN, "-vrdebug: '%s'\n", bootargs);
+ VrDebug = atoi(bootargs);
+ continue;
+ }
+ if (strncmp(bootargs, "-env", 4) == 0) {
+ NEXT_TOKEN();
+ key = bootargs;
+ NEXT_TOKEN();
+ val = bootargs;
+ debug(VRDBG_MAIN, "-env: '%s' '%s'\n", key, val);
+ update_argv(key, val);
+ }
+ if (strncmp(bootargs, "-h", 2) == 0) {
+ VrDebug |= VRDBG_HOLDIT;
+ }
+ NEXT_TOKEN();
+ }
+}
+
+STATIC VOID
+update_argv(char *key, char *val)
+{
+ struct argv_tab *atp = argv_tab;
+
+ for ( ; atp->key != NULL; ++atp) {
+ if (strcmp(key, atp->key) == 0) {
+ atp->val = val;
+ return;
+ }
+ }
+ if (atp >= &argv_tab[MAX_ARGC]) {
+ warn("You can't define any more argument variables\n");
+ return;
+ }
+ atp->key = key;
+ atp->val = val;
+ atp->which = BOTH;
+}
+
+#define CSI '\233'
+#define ESC '\033'
+
+STATIC INT
+select_boot(VOID)
+{
+ char *ids[16];
+ char *prop, c;
+ int i= 0, choices, chosen, countdown, csi, count;
+ debug(VRDBG_ENTRY,"select_boot: VOID BEGIN....\n");
+
+ //
+ // Determine how long to display the list of options:
+ //
+ prop = VrGetEnvironmentVariable("COUNTDOWN");
+ if (prop == NULL) {
+ countdown = 10;
+ } else {
+ countdown = atoi(prop);
+ }
+
+ //
+ // get the text list of possible options.
+ //
+ prop = VrGetEnvironmentVariable("LOADIDENTIFIER");
+ if (prop == NULL) {
+ return(0);
+ }
+
+ //
+ // tokenize the string of load options, creating pointers to each
+ // component of the string. Don't use strctok, since we need to
+ // worry about detecting null entries in the OsLoadOptions list.
+ //
+ ids[i++] = prop; // stuff the first one in the array....
+ while ((prop = index(prop, ';')) != NULL) {
+ *prop = '\0'; // change the separator to a null
+ prop++;
+ ids[i++] = prop;
+ }
+ choices = i;
+ while (i < 16) {
+ ids[i++] = NULL;
+ }
+
+ //
+ // here be the wheel of fortune: Makes yer choice and be off wid ya
+ //
+ chosen = 0;
+ csi = 0;
+ warn("\233H\233J"); // Clear screen
+ Salutation();
+ puts("\233""24;1HMake selection using arrow keys and 'Enter', or press ESC to cancel");
+ countdown += VrGetRelativeTime();
+again:
+ for (i = 0; i < choices; ++i) {
+ if (i == chosen) {
+ warn("\233%d;1H\233K\233%d;3H\233""7m* %s\233""m\n",
+ i+3, i+3, ids[i]);
+ } else {
+ warn("\233%d;1H\233K\233%d;5H%s\n", i+3, i+3, ids[i]);
+ }
+ }
+ i = 0;
+ warn("\233%d;1H\233K\n", choices+5);
+ while (VrGetReadStatus(0)) {
+ if (countdown == -1) {
+ continue;
+ }
+ if (VrGetRelativeTime() > (unsigned) countdown) {
+ goto out;
+ }
+ if (VrGetRelativeTime() != (unsigned) i) {
+ warn("\233%d;1H\233K\233%d;5HSeconds remaining: %d\n",
+ choices+5, choices+5, countdown - VrGetRelativeTime());
+ i = VrGetRelativeTime();
+ }
+ }
+ countdown = -1;
+ (void) VrRead(0, &c, 1, &count);
+ if (csi) {
+ switch (c) {
+ case 'A': chosen = max(chosen - 1, 0); break;
+ case 'B': chosen = min(chosen + 1, choices-1); break;
+ }
+ csi = 0;
+ } else {
+ switch (c) {
+ case CSI: csi = 1; break;
+ case '\r': goto out;
+ case '\n': goto out;
+ case ESC: OFExit();
+
+ case 'k': // vi
+ case '\020': // emacs
+ case '+': // good guesses
+ case '<':
+ chosen = max(chosen - 1, 0); break;
+ case 'j':
+ case '\016':
+ case '-':
+ case '>':
+ chosen = min(chosen + 1, choices-1); break;
+
+ case '\t':
+ if (++chosen == choices) {
+ chosen = 0;
+ }
+ break;
+ }
+ }
+ goto again;
+
+out:
+ warn("\233H\233J"); // Clear screen
+ //
+ // Given the chosen number, pull out the corresponding string, and
+ // setup the Bootpath and SystemPath variables:
+ //
+ Bootpath = choose_args("OSLOADER", "OsLoader", chosen);
+ SystemPath = choose_args("SYSTEMPARTITION", "SystemPartition", chosen);
+
+ //
+ // get the rest of the options.....
+ //
+ choose_args("OSLOADPARTITION", "OSLoadPartition", chosen);
+ choose_args("OSLOADOPTIONS", "OSLoadOptions", chosen);
+ choose_args("LOADIDENTIFIER", "LoadIdentifier", chosen);
+ choose_args("OSLOADFILENAME", "OSLoadFilename", chosen);
+
+ debug(VRDBG_ENTRY,"select_boot: VOID ....END\n");
+ return(1);
+}
+
+STATIC CHAR *
+choose_args( char *EnvVar, char *Varrrg, int achoice )
+{
+ char *prop, *cp;
+ int i= 0;
+ debug(VRDBG_ENTRY,
+ "choose_args: EnvVar: %s Varrrg: %s achoice: 0x%x BEGIN....\n",
+ *EnvVar, *Varrrg, achoice);
+ prop = VrGetEnvironmentVariable(EnvVar);
+ //debug(VRDBG_TEST, "\n@%d: prop is currently...%s:\n",i,prop);
+ if (prop == NULL) {
+ return(0);
+ }
+ prop = strcsep(prop, ';');
+ for (i = 0; i < achoice; ++i) {
+ if ((prop = strcsep(NULL, ';')) == NULL) {
+ return(0);
+ }
+ }
+ cp = zalloc(strlen(prop) +1 );
+ strcpy(cp, prop);
+ update_argv(Varrrg, cp);
+ //debug(VRDBG_TEST, "@%d: cp is set to...%s:\n",i,cp);
+ debug(VRDBG_ENTRY, "choose_args: ....END\n");
+ return( cp );
+}
+
+STATIC VOID
+find_boot_dev(VOID)
+{
+ phandle ph;
+ char *bootpath;
+ PCONFIGURATION_NODE node;
+
+ if (Bootpath) {
+ debug(VRDBG_MAIN, "Bootpath has been set from the command line\n");
+ return;
+ }
+ if (select_boot()) {
+ debug(VRDBG_MAIN, "We chose a boot device from LOADIDENTIFIER menu.\n");
+ return;
+ }
+
+ // Use whatever device we booted the veneer from.
+ ph = OFFinddevice("/chosen");
+ bootpath = get_str_prop(ph, "bootpath", NOALLOC);
+ if (bootpath == NULL) {
+ warn("find_boot_dev: No property '/chosen:bootpath'\n");
+ return;
+ }
+ debug(VRDBG_MAIN, "find_boot_dev: bootpath (len %d) '%s'\n",
+ strlen(bootpath), bootpath);
+ node = PathToNode(bootpath);
+ if (node == NULL) {
+ warn("find_boot_dev: Couldn't find node for '%s'\n", bootpath);
+ return;
+ }
+ Bootpath = NodeToArcPath(node);
+ bootpath = (char *)malloc(strlen(Bootpath) + strlen("partition(1)") + 1);
+ strcpy(bootpath, Bootpath);
+ strcat(bootpath, "partition(1)"); /* XXX */
+ free(Bootpath);
+ Bootpath = bootpath;
+ debug(VRDBG_MAIN, "find_boot_dev: bootpath '%s'\n", Bootpath);
+}
+
+/*
+ *
+ * ROUTINE: VOID read_ARC_env_vars(VOID)
+ *
+ * DESCRIPTIN:
+ * Initialize the arc argument table with the values contained in open
+ * firmware.
+ *
+ */
+
+STATIC VOID
+read_ARC_env_vars(VOID)
+{
+ struct argv_tab *atp;
+ char *val, *newval;
+
+ //
+ // for each variable in the argv_tab array, find the actual value
+ // this system has in firmware.
+ //
+ for (atp = argv_tab; atp < &argv_tab[MAX_ARGC] && atp->key; ++atp) {
+ if ((val = VrGetEnvironmentVariable(atp->key)) != NULL) {
+ newval = (char *) malloc(strlen(val) + 1);
+ strcpy(newval, val);
+ atp->val = newval;
+ }
+ }
+}
+
+STATIC VOID
+create_argv(VOID)
+{
+ struct argv_tab *atp;
+ char *osloader, *old_osloader = "";
+ char *buf;
+ phandle ph;
+ extern char *VeneerVersion();
+
+ /*
+ * First instantiate the boot partition string in the
+ * OS Loader arguments table. By the way, when we find
+ * STR_OSLOADER, save it to produce the argv[0] and OsLoader
+ * arguments.
+ */
+ for (atp = argv_tab; atp < &argv_tab[MAX_ARGC] && atp->key; ++atp) {
+ if (strcmp(atp->val, STR_XYZZY) == 0) {
+ atp->val = Bootpath;
+ }
+ if (strcmp(atp->key, "OsLoader") == 0) {
+ old_osloader = atp->val;
+ }
+ }
+
+ /*
+ * Initialize the argv/envp arrays.
+ */
+ VrArgc = VrEnvc = 0;
+ bzero((PCHAR) VrArgv, MAX_ARGC * sizeof(PCHAR));
+ bzero((PCHAR) VrEnvp, MAX_ENVC * sizeof(PCHAR));
+ VrEnvp[VrEnvc] = "";
+
+ /*
+ * Construct argv[0], the boot string (special case).
+ */
+ if (old_osloader[0] == '\\') {
+ osloader = zalloc(strlen(Bootpath) + strlen(old_osloader) + 1);
+ strcpy(osloader, Bootpath);
+ strcat(osloader, old_osloader);
+ } else {
+ osloader = old_osloader;
+ }
+ add_argv("", osloader);
+
+ /*
+ * Now walk the argv table, building the argv and envp
+ * arrays. When we encounter OsLoader, be sure to use the
+ * buffer we just built, rather than the table value.
+ */
+ for (atp = argv_tab; atp < &argv_tab[MAX_ARGC] && atp->key; ++atp) {
+ if (strcmp(atp->key, "OsLoader") == 0) {
+ atp->val = osloader;
+ }
+ if (atp->which != ENVONLY) {
+ add_argv(atp->key, atp->val);
+ }
+ if (atp->which != ARGVONLY) {
+ add_envp(atp->key, atp->val);
+ }
+ if (strcmp(atp->key, "SystemPartition" ) == 0 ){
+ atp->val = SystemPath;
+ }
+ }
+
+ /*
+ * Record the version strings.
+ */
+ ph = OFFinddevice("/openprom");
+ add_envp("FirmwareVersion", get_str_prop(ph, "model", NOALLOC));
+ add_envp("VeneerVersion", VeneerVersion());
+
+ /*
+ * Finally, take care of the console paths, set at runtime.
+ */
+ buf = VrFindConsolePath("stdin");
+ add_argv("ConsoleIn", buf);
+ add_envp("ConsoleIn", buf);
+ free(buf);
+
+ buf = VrFindConsolePath("stdout");
+ add_argv("ConsoleOut", buf);
+ add_envp("ConsoleOut", buf);
+ free(buf);
+}
+
+
+STATIC VOID
+add_argv(PCHAR key, PCHAR val)
+{
+ char *buf;
+ int len;
+
+ len = strlen(key);
+ if (len) {
+ len += 1; // for '='
+ }
+ len += strlen(val);
+ buf = (char *) zalloc(len+1);
+ strcpy(buf, key);
+ if (*buf != '\0') {
+ strcat(buf, "=");
+ }
+ strcat(buf, val);
+ VrArgv[VrArgc] = buf;
+ if ((buf = index(buf, ';')) != NULL) {
+ *buf = '\0';
+ }
+ debug(VRDBG_ARGV, "Argv[%d]: %s\n", VrArgc, VrArgv[VrArgc]);
+ VrArgc += 1;
+}
+
+/*
+ * ROUTINE: VOID add_envp( PCHAR, PCHAR )
+ *
+ * DESCRIPTION:
+ * Add the passed in name string and value into an array
+ * of string/value pairs that describes the environment for
+ * the arc program to be executed. The entry in the array is
+ * of the form "name=value", and is added to the beginning of
+ * the array.
+ *
+ * RETURN:
+ * Returns nothing.
+ *
+ */
+
+STATIC VOID
+add_envp(PCHAR key, PCHAR val)
+{
+ char *buf;
+ int len;
+
+ len = strlen(key);
+ if (len) {
+ len += 1; // for '='
+ }
+ len += strlen(val);
+ buf = (char *) zalloc(len+1);
+ strcpy(buf, VrCanonicalName(key));
+ if (*buf != '\0') {
+ strcat(buf, "=");
+ }
+ strcat(buf, val);
+ VrEnvp[VrEnvc+1] = VrEnvp[VrEnvc];
+ VrEnvp[VrEnvc] = buf;
+ debug(VRDBG_ENV, " Env[%d]: %s\n", VrEnvc, VrEnvp[VrEnvc]);
+ VrEnvc += 1;
+}
+
+static
+int
+is_mp_capable(ULONG VerRev)
+{
+ ULONG ver = (VerRev >> 16) & 0xFFFF;
+ ULONG rev = VerRev & 0xFFFF;
+
+ switch(ver) {
+
+ case PPC_604:
+ if ( rev > 0x0304 )
+ return(1);
+ break;
+
+ case PPC_604E:
+ return(1);
+
+ default:
+ return(0);
+
+ }
+ return(0);
+
+}
+
+
+//
+// The routines that follow initialize the System Parameter Block,
+// Firmware Vector Table, and Restart Blocks.
+//
+// Note the use of MAP() and UNMAP() macros. The kernel requires that
+// addresses in the System Parameter Block and Restart Blocks be
+// VIRTUAL, not physical. Therefore, all addresses that may be presented
+// to the kernel must be mapped to KSEG0; i.e., they must be in the
+// range starting at 0x80000000.
+//
+
+STATIC PRESTART_BLOCK last_rstb = 0;
+
+STATIC PRESTART_BLOCK
+InitRestartBlocks(PCONFIGURATION_NODE node, PRESTART_BLOCK rstb)
+{
+ PRESTART_BLOCK new_rstb;
+
+ debug(VRDBG_ENTRY, "InitRestartBlocks: Begin(0x%x, 0x%x)...\n",node, rstb);
+ VRDBG(VRDBG_ENTRY, vr_dump_config_node(node));
+
+ if (node->Component.Class == ProcessorClass &&
+ node->Component.Type == CentralProcessor) {
+
+ // Figure out where the next node's space should be.
+ if (rstb) {
+ new_rstb = (PRESTART_BLOCK) ((PCHAR) rstb + sizeof(RESTART_BLOCK));
+ } else {
+ new_rstb = (PRESTART_BLOCK) ((PCHAR) SYSTEM_BLOCK +
+ SYSTEM_BLOCK->Length + SYSTEM_BLOCK->FirmwareVectorLength);
+ }
+
+ // Claim the space and turn it into a restart block.
+ if (CLAIM((VOID *)new_rstb, sizeof(RESTART_BLOCK)) == -1) {
+ fatal("Couldn't claim RESTART BLOCK\n");
+ }
+
+ if (rstb) {
+ rstb->NextRestartBlock = (PRESTART_BLOCK) UNMAP(new_rstb);
+ }
+ rstb = new_rstb;
+ last_rstb = new_rstb;
+
+ bzero((PCHAR) rstb, sizeof(RESTART_BLOCK));
+ rstb->Signature = ARC_RESTART_BLOCK_SIGNATURE;
+ rstb->Version = 1;
+ rstb->Revision = 2;
+ rstb->Length = sizeof(RESTART_BLOCK);
+ rstb->SaveAreaLength = sizeof(PPC_RESTART_STATE);
+// rstb->BootStatus.BootFinished = 1;
+ rstb->BootStatus.ProcessorReady = 1;
+ rstb->ProcessorId = node->Component.Key;
+ if (rstb->ProcessorId == 0) {
+ rstb->BootStatus.ProcessorStart = 1;
+ rstb->BootStatus.ProcessorRunning = 1;
+ } else {
+ rstb->BootStatus.ProcessorStart = 0;
+ }
+ }
+
+ if (node->Child) {
+ rstb = InitRestartBlocks(node->Child, rstb);
+ }
+ if (node->Peer) {
+ rstb = InitRestartBlocks(node->Peer, rstb);
+ }
+
+ debug(VRDBG_ENTRY, "InitRestartBlocks: ....Exit\n");
+ return (rstb);
+}
+
+STATIC VOID
+SumRestartBlocks(PRESTART_BLOCK rstb)
+{
+ PLONG up = (PLONG) rstb;
+ LONG accum = 0;
+
+ debug(VRDBG_ENTRY, "SumRestartBlocks: Begin(0x%x)....\n", rstb);
+ rstb->CheckSum = 0;
+ while (up < (PLONG) ((PCHAR) rstb + sizeof(RESTART_BLOCK))) {
+ accum += *up++;
+ }
+ rstb->CheckSum = -accum;
+ debug(VRDBG_ENTRY, "SumRestartBlocks: ....Exit\n", rstb);
+}
+
+STATIC int
+IdleCPU(PRESTART_BLOCK rstb, int stopFlag)
+{
+ STATIC PVOID IdleLoop = 0;
+ STATIC PULONG Bootp;
+ STATIC ULONG ProcRev=0;
+ STATIC INT mismatchFlag = 0;
+ ULONG IdleLoopSize;
+ ULONG res, timeout;
+ extern PVOID ArcPoll, EndArcPoll;
+
+ // cpu0 is always successful so that we can have a
+ // uniprocessor system in hand
+ if (rstb->ProcessorId == 0) {
+ ProcRev = VrGetProcRev();
+ if (!is_mp_capable(ProcRev))
+ mismatchFlag = 1;
+ return(0);
+ }
+
+ // The processor idle loop must be in FirmwarePermanent memory,
+ // so that it's not disturbed by kernel startup. Identify a piece
+ // of memory just after the last restart block and copy in the
+ // idle loop code.
+
+ if (IdleLoop == 0) {
+ IdleLoop = (PCHAR) last_rstb + sizeof(RESTART_BLOCK);
+ IdleLoopSize = (ULONG) &EndArcPoll - (ULONG) &ArcPoll;
+
+ // Pad to make room for BootStatus and SaveArea variables.
+ Bootp = (PULONG) IdleLoop;
+ (PCHAR) IdleLoop += 3 * sizeof(ULONG);
+ IdleLoopSize += 3 * sizeof(ULONG);
+
+ if (CLAIM(IdleLoop, IdleLoopSize) == -1) {
+ fatal("Couldn't claim MP idle loop\n");
+ }
+ bcopy((PCHAR) &ArcPoll, IdleLoop, IdleLoopSize);
+ VrFlushAllCaches();
+ }
+
+ //
+ // Set this processor spinning in the new idle loop.
+ // XXX - To do: change this to CIF.
+ // Since we're running in virtual mode that is mapped virtual 0
+ // to physical 0, this assignment translates directly into the
+ // real mode addresses the IdleCPU routine will end up executing.
+ //
+ Bootp[0] = 0; // processor version returned by the cpu
+ Bootp[1] = (ULONG) &rstb->BootStatus;
+ Bootp[2] = (ULONG) &rstb->u.SaveArea;
+
+ // Give the other processor plenty of time to start up: he may be
+ // executing debug printouts and other slow tasks before switching.
+ // Five seconds should be more than adequate.
+
+ debug(VRDBG_TMP, "Executing non 0 processor at 0x%x\n", IdleLoop);
+ res = 0;
+ if (OFInterpret(1, 3, &res, "cpu-execute-code", rstb->ProcessorId, IdleLoop) != 0) {
+ return(-1);
+ }
+ if (res == 0)
+ return(-1);
+
+ //
+ // wait a small amount of time for the other processor to
+ // start up. Since VrGetRelative time returns the time since
+ // power-on/reset, tack on a few seconds for the waiting period.
+ //
+ //timeout = VrGetRelativeTime() + (5 * 1000);
+ timeout = VrGetRelativeTime() + (5 * 1); // 5 seconds should be
+ // long enough
+
+ do {
+ if (Bootp[1] == 0x1234) {
+ debug(VRDBG_TMP,"ProcRev = 0x%x; return = 0x%x\n",
+ Bootp[0], Bootp[1]);
+ if ( Bootp[0] != ProcRev || mismatchFlag || stopFlag) {
+ Bootp[1] = 0xBAD;
+ return(-1);
+ } else {
+ Bootp[1] = 0xCAFE;
+ return(0);
+ }
+ }
+ } while (VrGetRelativeTime() < timeout);
+ fatal("Processor %d failed to enter MP idle loop.\n", rstb->ProcessorId);
+}
+
+
+/*
+ * Routine Description:
+ * This routine initializes the firmware vector in the system parameter
+ * block.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+
+STATIC VOID
+VrInitSystem(VOID)
+{
+ LONG i;
+ LONG FirmwareVectorLen;
+ PRESTART_BLOCK rstb, PrevRstb;
+ int NumOfCpu = 0 , NumProc = 0;
+ ULONG ProcMask = 0, maskscan = 0;
+ PCHAR evp;
+
+ debug(VRDBG_ENTRY, "VrInitSystem: BEGIN....\n");
+ //
+ // Initialize the system parameter block
+ //
+ FirmwareVectorLen = (ULONG)MaximumRoutine * sizeof(ULONG);
+ i = sizeof(SYSTEM_PARAMETER_BLOCK) + FirmwareVectorLen;
+ debug(VRDBG_ENTRY, "VrInitSystem: i(0x%x), FirmwareVectorLen(0x%x) set:\n",
+ i, FirmwareVectorLen);
+
+#if 0
+ //
+ // THis is now down in a different routine called by main.
+ //
+ //
+ // attempting to setup all the claiming early on
+ //
+ if (use_bat_mapping) {
+ res = claim((PVOID) SYSTEM_BLOCK, i);
+ } else {
+ res = claimreal((PVOID) SYSTEM_BLOCK, i);
+ }
+ if (res == -1) {
+ fatal("Couldn't claim SYSTEM PARAMETER BLOCK\n");
+ }
+ bzero((PCHAR)SYSTEM_BLOCK, i);
+#endif
+
+
+ debug(VRDBG_ENTRY, "VrInitSystem: Init SYSTEM_BLOCK.. \n");
+ SYSTEM_BLOCK->Signature = SYSTEM_BLOCK_SIGNATURE;
+ SYSTEM_BLOCK->Version = ARC_VERSION;
+ SYSTEM_BLOCK->Revision = ARC_REVISION;
+ SYSTEM_BLOCK->Length = sizeof(SYSTEM_PARAMETER_BLOCK);
+
+ SYSTEM_BLOCK->FirmwareVector =
+ (PVOID) UNMAP((PCHAR) SYSTEM_BLOCK + SYSTEM_BLOCK->Length);
+ SYSTEM_BLOCK->FirmwareVectorLength = FirmwareVectorLen;
+
+ //
+ // Initialize the restart blocks.
+ //
+ debug(VRDBG_ENTRY, "VrInitSystem: Init restart blocks\n");
+ SYSTEM_BLOCK->RestartBlock = (PRESTART_BLOCK) UNMAP((PCHAR) SYSTEM_BLOCK +
+ SYSTEM_BLOCK->Length + SYSTEM_BLOCK->FirmwareVectorLength);
+ if (InitRestartBlocks(RootNode, 0)) {
+ rstb = (PRESTART_BLOCK) MAP(SYSTEM_BLOCK->RestartBlock);
+ PrevRstb = 0;
+ NumOfCpu = 0;
+ ProcMask = 0xFFFFFFFF;
+ if ( (evp = VrGetEnvironmentVariable("PROCESSORS")) != NULL )
+ ProcMask = atoi(evp) | 1;
+ maskscan = 1;
+ while (rstb) {
+ SumRestartBlocks(rstb);
+
+ if (IdleCPU(rstb,(ProcMask&maskscan) == 0 ) == -1) {
+ ProcMask &= ~maskscan; // clear the bit
+ // remove the restart block
+ PrevRstb->NextRestartBlock = rstb->NextRestartBlock;
+ } else {
+ NumOfCpu++;
+ PrevRstb = rstb;
+ }
+ maskscan <<= 1;
+ rstb = (PRESTART_BLOCK) MAP(PrevRstb->NextRestartBlock);
+ }
+ } else {
+ SYSTEM_BLOCK->RestartBlock = 0;
+ }
+
+
+ //
+ // Temporarily make all firmware vector to point to an error routine.
+ //
+ for (i=LoadRoutine; i < MaximumRoutine; i++) {
+ (VR_NOT_YET_ROUTINE)SYSTEM_BLOCK->FirmwareVector[i] = VrNotYet;
+ }
+
+ //
+ // Initialize the firmware vectors for other functions.
+ //
+ VrEnvInitialize();
+ VrMemoryInitialize();
+ VrIoInitialize();
+ VrDisplayInitialize();
+ VrLoadInitialize();
+ VrRestartInitialize();
+ VrConfigInitialize();
+ VrTimeInitialize();
+ debug(VRDBG_ENTRY, "VrInitSystem: .....END\n");
+}
+
+STATIC VOID
+VrNotYet( VOID )
+{
+ fatal("This ARC function is not yet implemented\n");
+}
+
+
+STATIC VOID
+move_multi_to_root(PCONFIGURATION_NODE node)
+{
+ PCONFIGURATION_NODE child = node->Child;
+ PCONFIGURATION_NODE peer = node->Peer;
+ PCONFIGURATION_NODE n;
+ ULONG key;
+
+ debug(VRDBG_ENTRY, "move_multi_to_root: node 0x%x\n", node);
+ if (node == 0) {
+ debug(VRDBG_TREE, "move_multi_to_root: node is 0, return.\n");
+ return;
+ }
+ debug(VRDBG_TREE, "MMTR: move node: 0x%x to child of ROOT\n",node);
+ VRDBG(VRDBG_TREE, vr_dump_config_node(node));
+
+ // Examine the first child, and keep promoting it/them until
+ // the first child is no longer of type multi.
+
+ while ( (child) && (child->Component.Type == MultiFunctionAdapter)) {
+ for (n = RootNode->Child, key = 0; n->Peer; n = n->Peer) {
+ if (n->Component.Type == MultiFunctionAdapter) {
+ key = max(key, n->Component.Key);
+ }
+ }
+ if (n->Component.Type == MultiFunctionAdapter) {
+ key = max(key, n->Component.Key);
+ }
+ child->Parent = RootNode;
+ n->Peer = child;
+ node->Child = child->Peer;
+ child->Peer = 0;
+ child->Component.Key = key + 1;
+ child = node->Child;
+ }
+
+ // Process the entire Child branch.
+
+ move_multi_to_root(child);
+
+ // Now for the Peer branch: first, if our parent is the root,
+ // there's no need to promote the peer node, so skip the next step.
+
+ if (node->Parent != RootNode) {
+
+ // As before, promote peers until the peer isn't a multi node...
+
+ while (peer && peer->Component.Type == MultiFunctionAdapter) {
+ for (n = RootNode->Child, key = 0; n->Peer; n = n->Peer) {
+ if (n->Component.Type == MultiFunctionAdapter) {
+ key = max(key, n->Component.Key);
+ }
+ }
+ if (n->Component.Type == MultiFunctionAdapter) {
+ key = max(key, n->Component.Key);
+ }
+ peer->Parent = RootNode;
+ n->Peer = peer;
+ node->Peer = peer->Peer;
+ peer->Peer = 0;
+ peer->Component.Key = key + 1;
+ peer = node->Peer;
+ }
+ }
+
+ // ...and process the Peer branch. Since our traversal is depth-first
+ // and promoted nodes are appended to the RootNode's Child's Peer branch
+ // (and are thus processed last), this routine should suffice to traverse
+ // the entire tree.
+
+ move_multi_to_root(peer);
+}
+
+
+LONG
+claimreal(PVOID addr, ULONG size)
+{
+ if (claimphys((PVOID) MAP(addr), size, 0) == -1) {
+ return(-1);
+ }
+ return(map((PVOID) MAP(addr), addr, size, (ULONG) -1));
+}
+
+STATIC LONG
+claimphys(PVOID physical, ULONG size, ULONG align)
+{
+ static ihandle memih = 0;
+ ULONG base;
+
+ if (memih == 0) {
+ if((memih = get_int_prop(OFFinddevice("/chosen"), "memory")) == 0) {
+ fatal("Couldn't open the memory node");
+ }
+ }
+ return(OFCallMethod(1, 5, &base,
+ "claim", memih, align, size, (ULONG) physical));
+}
+
+STATIC LONG
+map(PVOID physical, PVOID virtual, ULONG size, ULONG mode)
+{
+ static ihandle mmuih = 0;
+
+ if (mmuih == 0) {
+ if((mmuih = get_int_prop(OFFinddevice("/chosen"), "mmu")) == 0) {
+ fatal("Couldn't open the MMU node");
+ }
+ }
+ return(OFCallMethod(0, 6, 0,
+ "map", mmuih, mode, size, virtual, (ULONG) physical));
+}
+
+/*
+ * Because the PowerPC port is based on the MIPS port, and no one saw fit
+ * to re-examine assumptions in the light of the PowerPC architecture,
+ * the NT kernel et al. are expected to reside in kseg0 (8000.0000-a000.000).
+ * Set up a virtual mapping for this region.
+ */
+STATIC VOID
+VrKseg0(VOID)
+{
+ ihandle ih;
+
+ debug(VRDBG_MAIN, "Mapping in kseg0...\n");
+ ih = get_int_prop(OFFinddevice("/chosen"), "mmu");
+ if (ih == 0) {
+ fatal("Couldn't open the MMU node; kseg0 translation not set up.\n");
+ }
+ OFCallMethod(0, 6, 0, "map", ih, -2, 0x800000, 0x80000000, 0);
+ return;
+}
+
+/*
+ * XXX - This is a hack for the AMD79C974 Ethernet chip driver: the driver
+ * assumes the chip is on the ISA bus.
+ */
+
+STATIC void
+move_amd_to_isa_hack(void)
+{
+ phandle ph;
+ PCONFIGURATION_NODE amdnode, peernode, isanode;
+
+ if ((ph = OFFinddevice("/pci/AMD,79c970@4")) == -1) {
+ debug(VRDBG_MAIN, "No AMD ethernet found\n");
+ return;
+ }
+
+ peernode = PathToNode("/pci");
+ peernode = peernode->Child;
+
+ if (peernode->OfPhandle == ph) {
+ amdnode = peernode;
+ peernode->Parent->Child = peernode->Peer;
+ } else {
+ while (peernode->Peer && (peernode->Peer->OfPhandle != ph)) {
+ peernode = peernode->Peer;
+ }
+ amdnode = peernode->Peer;
+ peernode->Peer = amdnode->Peer;
+ }
+
+ isanode = PathToNode("/pci/isa");
+ if (isanode->Child == NULL) {
+ isanode->Child = amdnode;
+ amdnode->Peer = NULL;
+ } else {
+ peernode = isanode->Child;
+ while (peernode->Peer) {
+ peernode = peernode->Peer;
+ }
+ amdnode->Peer = peernode->Peer;
+ peernode->Peer = amdnode;
+ }
+ amdnode->Parent = isanode;
+}
+
+STATIC void
+move_ide_to_isa_hack(void)
+{
+ PCONFIGURATION_NODE node, idenode = 0, isanode;
+ int lastkey = 0;
+
+ isanode = PathToNode("/pci/isa");
+ node = isanode->Child;
+ while (node) {
+ if (strcmp(node->ComponentName, "disk") == 0) {
+ lastkey = max(lastkey, (int) node->Component.Key);
+ }
+ if (strcmp(node->Component.Identifier, "IDE") == 0) {
+ idenode = node;
+ }
+ node = node->Peer;
+ }
+ if (idenode == 0) {
+ return;
+ }
+
+ node = isanode->Child;
+ while (node->Peer != idenode) {
+ node = node->Peer;
+ }
+ node->Peer = node->Peer->Peer; /* Bypass ide node */
+ while (node->Peer) {
+ node = node->Peer;
+ }
+ node->Peer = idenode->Child;
+
+ while (node->Peer) {
+ node->Peer->Parent = node->Parent;
+ if (strcmp(node->Peer->ComponentName, "disk") == 0) {
+ node->Peer->Component.Key = ++lastkey;
+ }
+ node = node->Peer;
+ }
+}
+
+/*
+ * move_scsi_children_to_ide_hack() moves the children (e.g. disk and cdrom)
+ * of the SCSI node to be children of the IDE node, and changes the IDE's
+ * phandle pointer to point to the Open Firmware SCSI node.
+ *
+ * This egregious hack is necessary for the initial release of IBM's "Harley"
+ * evaluation system. On that system, IBM's portable boot loader misrepresents
+ * the hardware by reporting the SCSI disk and SCSI CD-ROM devices as children
+ * of the IDE node in the ARC tree! The IDE and SCSI nodes themselves are in
+ * the correct places in the ARC tree, but the children are in the wrong
+ * place. The enviroment variables that specify the locations of the OSLOADER
+ * and so forth collude in this fiction by specifying paths like
+ * multi(1)scsi(0)disk(0)rdisk(3)partition(2), which is the path through
+ * the IDE node (which, for reasons not specific to Harley, is of class
+ * "scsi"). I do not know exactly what NT does in order to compensate for
+ * this lie.
+ */
+
+STATIC void
+move_scsi_children_to_ide_hack(void)
+{
+ PCONFIGURATION_NODE node, idenode = 0, scsinode = 0;
+
+ if (OFGetproplen(OFFinddevice("/openprom"),"arc-scsi-to-ide") < 0) {
+ return;
+ }
+
+ idenode = PathToNode("/pci/isa/ide");
+ scsinode = PathToNode("/pci/scsi");
+
+ if (idenode == 0 || scsinode == 0) {
+ return;
+ }
+
+ /* Move SCSI children underneath IDE */
+ idenode->Child = scsinode->Child;
+
+ scsinode->Child = 0;
+
+ /* Reparent SCSI children to IDE */
+ for (node = idenode->Child; node != 0; node = node->Peer) {
+ node->Parent = idenode; /* Reparent nodes */
+ }
+
+ /* Point the IDE node to the Open Firmware SCSI node so Open will work */
+ idenode->OfPhandle = scsinode->OfPhandle;
+
+ idenode->Component.Type = ScsiAdapter;
+ idenode->ComponentName = "scsi";
+}
+
+STATIC VOID
+VrInitSystemBlock()
+{
+ LONG i;
+ LONG FirmwareVectorLen;
+ //
+ // Initialize the system parameter block
+ //
+ FirmwareVectorLen = (ULONG)MaximumRoutine * sizeof(ULONG);
+ i = sizeof(SYSTEM_PARAMETER_BLOCK) + FirmwareVectorLen;
+
+ if (CLAIM((PVOID) SYSTEM_BLOCK, i) == -1) {
+ fatal("Couldn't claim SYSTEM PARAMETER BLOCK\n");
+ }
+ bzero((PCHAR)SYSTEM_BLOCK, i);
+ return;
+}
+
diff --git a/private/ntos/boot/veneer/vrmalloc.c b/private/ntos/boot/veneer/vrmalloc.c
new file mode 100644
index 000000000..c0872f254
--- /dev/null
+++ b/private/ntos/boot/veneer/vrmalloc.c
@@ -0,0 +1,355 @@
+/*
+ *
+ * Copyright 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrmalloc.c $
+ * $Revision: 1.6 $
+ * $Date: 1996/02/17 00:41:29 $
+ * $Locker: $
+ *
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * A "smarter" malloc William L. Sebok
+ * Sept. 24, 1984
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * If n = the size of an area rounded DOWN to the nearest power of two,
+ * all free areas of memory whose length is the same index n is organized
+ * into a chain with other free areas of index n. A request for memory
+ * takes the first item in the chain whose index is the size of the
+ * request rounded UP to the nearest power of two. If this chain is
+ * empty the next higher chain is examined. If no larger chain has memory
+ * then new memory is allocated. Only the amount of new memory needed is
+ * allocated. Any old free memory left after an allocation is returned
+ * to the free list. Extra new memory returned because of rounding
+ * to page boundaries is returned to free list.
+ *
+ * All memory areas (free or busy) handled by malloc are also chained
+ * sequentially by increasing address. When memory is freed it is
+ * merged with adjacent free areas, if any. If a free area of memory
+ * ends at the end of memory (i.e. at the break), the break is
+ * contracted, freeing the memory back to the system.
+ *
+ * Notes:
+ * ov_length field includes sizeof(struct overhead)
+ * adjacency chain includes all memory, allocated plus free.
+ */
+
+#include "veneer.h"
+
+#define MAGIC_FREE 0x548a934c
+#define MAGIC_BUSY 0xc139569a
+
+#define NBUCKETS 24
+#define NALIGN 4
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+};
+
+struct overhead {
+ struct qelem ov_adj; /* adjacency chain pointers */
+ struct qelem ov_buk; /* bucket chain pointers */
+ long ov_magic;
+ unsigned long ov_length;
+};
+
+char endfree = 0;
+struct qelem adjhead = { &adjhead, &adjhead };
+struct qelem buckets[NBUCKETS] = {
+ &buckets[0], &buckets[0],
+ &buckets[1], &buckets[1],
+ &buckets[2], &buckets[2],
+ &buckets[3], &buckets[3],
+ &buckets[4], &buckets[4],
+ &buckets[5], &buckets[5],
+ &buckets[6], &buckets[6],
+ &buckets[7], &buckets[7],
+ &buckets[8], &buckets[8],
+ &buckets[9], &buckets[9],
+ &buckets[10], &buckets[10],
+ &buckets[11], &buckets[11],
+ &buckets[12], &buckets[12],
+ &buckets[13], &buckets[13],
+ &buckets[14], &buckets[14],
+ &buckets[15], &buckets[15],
+ &buckets[16], &buckets[16],
+ &buckets[17], &buckets[17],
+ &buckets[18], &buckets[18],
+ &buckets[19], &buckets[19],
+ &buckets[20], &buckets[20],
+ &buckets[21], &buckets[21],
+ &buckets[22], &buckets[22],
+ &buckets[23], &buckets[23],
+};
+
+/*
+ * The following macros depend on the order of the elements in struct overhead
+ */
+#define TOADJ(p) ((struct qelem *)(p))
+#define FROMADJ(p) ((struct overhead *)(p))
+#define FROMBUK(p) ((struct overhead *)( (char *)p - sizeof(struct qelem)))
+#define TOBUK(p) ((struct qelem *)( (char *)p + sizeof(struct qelem)))
+
+#ifndef CURBRK
+#define CURBRK sbrk(0)
+#endif CURBRK
+
+STATIC void insque(), remque();
+
+#ifdef NULL
+#undef NULL
+#endif
+#define NULL 0
+#ifdef debug
+# define ASSERT(p,q) if (!(p)) fatal(q)
+#else
+# define ASSERT(p,q)
+#endif
+
+#define ALIGN(n, granule) ((n + ((granule)-1)) & ~((granule)-1))
+
+char *
+malloc(nbytes)
+ unsigned nbytes;
+{
+ register struct overhead *p, *q;
+ register int surplus = 0;
+ register struct qelem *bucket;
+ nbytes = ALIGN(nbytes, NALIGN) + sizeof(struct overhead);
+ bucket = &buckets[log2(nbytes-1) + 1]; /* log2 rounded up */
+ for (p = NULL; bucket < &buckets[NBUCKETS]; bucket++) {
+ if (bucket->q_forw != bucket) {
+ /* remove from bucket chain */
+ p = FROMBUK(bucket->q_forw);
+ ASSERT(p->ov_magic == MAGIC_FREE, "\nmalloc: Entry \
+not marked FREE found on Free List!\n");
+ remque(TOBUK(p));
+ surplus = p->ov_length - nbytes;
+ break;
+ }
+ }
+ if (p == NULL) {
+#ifdef USE_SBRK
+ register int i;
+ p = (struct overhead *)CURBRK;
+ if ((int)p == -1) {
+ return(NULL);
+ }
+ if (i = (int)p&(NALIGN-1)) {
+ sbrk(NALIGN-i);
+ }
+ p = (struct overhead *)sbrk(nbytes);
+ if ((int)p == -1) {
+ return(NULL);
+ }
+ q = (struct overhead *)CURBRK;
+ if ((int)q == -1) {
+ return(NULL);
+ }
+ p->ov_length = (char *)q - (char *)p;
+ surplus = p->ov_length - nbytes;
+ /* add to end of adjacency chain */
+ ASSERT((FROMADJ(adjhead.q_back)) < p, "\nmalloc: Entry in \
+adjacency chain found with address lower than Chain head!\n" );
+ insque(TOADJ(p),adjhead.q_back);
+#else
+ struct qelem *pp;
+ int alloc_size = ALIGN(nbytes, PAGE_SIZE);
+
+ p = (struct overhead *)alloc(alloc_size, NALIGN);
+ if ((int)p == -1) {
+ return(NULL);
+ }
+ p->ov_length = alloc_size;
+ surplus = p->ov_length - nbytes;
+
+ /* add to adjacency chain in the correct place */
+ for (pp = adjhead.q_forw; pp != &adjhead; pp = pp->q_forw) {
+ if (p < FROMADJ(pp)) {
+ break;
+ }
+ }
+ ASSERT(pp == &adjhead || (p < FROMADJ(pp)),
+ "\nmalloc: Bogus insertion in adjacency list\n");
+ insque(TOADJ(p),pp->q_back);
+#endif
+ }
+ if (surplus > sizeof(struct overhead)) {
+ /* if big enough, split it up */
+ q = (struct overhead *)( (char *)p + nbytes);
+ q->ov_length = surplus;
+ p->ov_length = nbytes;
+ q->ov_magic = MAGIC_FREE;
+ /* add surplus into adjacency chain */
+ insque(TOADJ(q),TOADJ(p));
+ /* add surplus into bucket chain */
+ insque(TOBUK(q),&buckets[log2(surplus)]);
+ }
+ p->ov_magic = MAGIC_BUSY;
+ return((char*)p + sizeof(struct overhead));
+}
+
+void
+free(mem)
+register char *mem;
+{
+ register struct overhead *p, *q;
+ if (mem == NULL) {
+ return;
+ }
+ p = (struct overhead *)(mem - sizeof(struct overhead));
+ if (p->ov_magic == MAGIC_FREE) {
+ return;
+ }
+ if (p->ov_magic != MAGIC_BUSY) {
+ fatal("attempt to free memory not allocated with malloc!\n");
+ }
+ q = FROMADJ((TOADJ(p))->q_back);
+ if (q != FROMADJ(&adjhead)) { /* q is not the first list item */
+ ASSERT(q < p, "\nfree: While trying to merge a free area with \
+a lower adjacent free area,\n addresses were found out of order!\n");
+ /* If lower segment can be merged */
+ if ((q->ov_magic == MAGIC_FREE) &&
+ ((char *)q + q->ov_length == (char *)p) ) {
+
+ /* remove lower address area from bucket chain */
+ remque(TOBUK(q));
+ /* remove upper address area from adjacency chain */
+ remque(TOADJ(p));
+ q->ov_length += p->ov_length;
+ p->ov_magic = NULL;
+ p = q;
+ }
+ }
+ q = FROMADJ((TOADJ(p))->q_forw);
+ if (q != FROMADJ(&adjhead)) { /* q is not the last list item */
+ /* upper segment can be merged */
+ ASSERT(q > p, "\nfree: While trying to merge a free area with \
+a higher adjacent free area,\n addresses were found out of order!\n");
+ if ( (q->ov_magic == MAGIC_FREE) &&
+ ((char *)p + p->ov_length == (char *)q) ) {
+
+ /* remove upper from bucket chain */
+ remque(TOBUK(q));
+ /* remove upper from adjacency chain */
+ remque(TOADJ(q));
+ p->ov_length += q->ov_length;
+ q->ov_magic = NULL;
+ }
+ }
+#ifdef USE_SBRK
+ /* freed area is at end of memory */
+ if ((endfree && adjhead.q_back == TOADJ(p)) &&
+ ((char*)p + p->ov_length == (char *)CURBRK) ) {
+
+ /* remove from end of adjacency chain */
+ remque(adjhead.q_back);
+ /* release memory to system */
+ sbrk( -((int)(p->ov_length)));
+ return;
+ }
+#endif
+ p->ov_magic = MAGIC_FREE;
+ /* place in bucket chain */
+ insque(TOBUK(p),&buckets[log2(p->ov_length)]);
+ return;
+}
+
+char *
+realloc(mem,nbytes)
+register char *mem; unsigned nbytes;
+{
+ register char *newmem;
+ register struct overhead *p, *q;
+ register int surplus;
+ if (mem == NULL) {
+ return(malloc(nbytes));
+ }
+ if(mem > (char*)FROMADJ(adjhead.q_back) + sizeof(struct overhead)) {
+ return(NULL);
+ }
+
+ p = (struct overhead *)(mem - sizeof(struct overhead));
+ nbytes = (nbytes + (NALIGN-1)) & (~(NALIGN-1));
+ if ( (p->ov_magic == MAGIC_BUSY) && (q = FROMADJ(adjhead.q_back)) != p
+ && (q->ov_magic != MAGIC_FREE || (FROMADJ(q->ov_adj.q_back) != p)) ) {
+
+ free(mem);
+ }
+ if( (p->ov_magic == MAGIC_BUSY || p->ov_magic == MAGIC_FREE)
+ && (surplus = p->ov_length - nbytes - sizeof(struct overhead)) >= 0 ) {
+ if (surplus > sizeof(struct overhead)) {
+ /* return surplus to free list */
+ nbytes += sizeof(struct overhead);
+#ifdef USE_SBRK
+ /* freed area is at end of memory */
+ if ( endfree && adjhead.q_back == TOADJ(p)
+ && (char*)p + p->ov_length == (char *)CURBRK ) {
+ /* release memory to system */
+ sbrk(-surplus);
+ } else
+#endif
+ {
+ q = (struct overhead *)( (char *)p + nbytes);
+ q->ov_length = surplus;
+ q->ov_magic = MAGIC_FREE;
+ insque(TOADJ(q),TOADJ(p));
+ insque(TOBUK(q),&buckets[log2(surplus)]);
+ }
+ p->ov_length = nbytes;
+ }
+ if (p->ov_magic == MAGIC_FREE) {
+ remque(TOBUK(p));
+ p->ov_magic = MAGIC_BUSY;
+ }
+ return(mem);
+ }
+ newmem = malloc(nbytes);
+ if (newmem != mem && newmem != NULL) {
+ register unsigned n;
+ if (p->ov_magic == MAGIC_BUSY || p->ov_magic == MAGIC_FREE) {
+ n = p->ov_length - sizeof(struct overhead);
+ nbytes = (nbytes < n) ? nbytes : n ;
+ }
+ bcopy(mem,newmem,nbytes);
+ }
+ if (p->ov_magic == MAGIC_BUSY) {
+ free(mem);
+ }
+ return(newmem);
+}
+
+log2(n)
+register int n;
+{
+ register int i = 0;
+ while ((n >>= 1) > 0) {
+ i++;
+ }
+ return(i);
+}
+
+void
+insque(item,queu)
+register struct qelem *item, *queu;
+{
+ register struct qelem *pueu;
+ pueu = queu->q_forw;
+ item->q_forw = pueu;
+ item->q_back = queu;
+ queu->q_forw = item;
+ pueu->q_back = item;
+}
+
+void
+remque(item)
+register struct qelem *item;
+{
+ register struct qelem *queu, *pueu;
+ pueu = item->q_forw;
+ queu = item->q_back;
+ queu->q_forw = pueu;
+ pueu->q_back = queu;
+}
diff --git a/private/ntos/boot/veneer/vrmemory.c b/private/ntos/boot/veneer/vrmemory.c
new file mode 100644
index 000000000..da9568e7c
--- /dev/null
+++ b/private/ntos/boot/veneer/vrmemory.c
@@ -0,0 +1,481 @@
+/*
+ *
+ * Copyright (c) 1994 FirePower Systems, Inc.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrmemory.c $
+ * $Revision: 1.19 $
+ * $Date: 1996/06/17 02:55:43 $
+ * $Locker: $
+ *
+ * Module Name:
+ * vrmemory.c
+ *
+ * Authour:
+ * Shin Iwamoto at FirePower Systems, Inc.
+ *
+ * History:
+ * 10-Sep-94 Shin Iwamoto at FirePower Systems, Inc.
+ * Added for ExecuteProg. Added comments.
+ * 07-Sep-94 Shin Iwamoto at FirePower Systems, Inc.
+ * Recreated.
+ */
+
+
+#include "veneer.h"
+
+//
+// Define memory allocation structure.
+//
+typedef struct _VR_MEMORY_DESCRIPTOR {
+ struct _VR_MEMORY_DESCRIPTOR *NextEntry;
+ MEMORY_DESCRIPTOR MemoryEntry;
+} VR_MEMORY_DESCRIPTOR, *PVR_MEMORY_DESCRIPTOR;
+
+PVR_MEMORY_DESCRIPTOR VrMemoryListOrig = (PVR_MEMORY_DESCRIPTOR) NULL;
+
+//
+// Function declaration
+//
+STATIC PVR_MEMORY_DESCRIPTOR SearchMemoryList(ULONG, ULONG);
+STATIC VOID SplitDesc(PVR_MEMORY_DESCRIPTOR, ULONG, ULONG, MEMORY_TYPE);
+
+STATIC PCHAR
+MemoryTypeTable[] = {
+ "MemoryExceptionBlock",
+ "MemorySystemBlock",
+ "MemoryFree",
+ "MemoryBad",
+ "MemoryLoadedProgram",
+ "MemoryFirmwareTemporary",
+ "MemoryFirmwarePermanent",
+ "MemoryFreeContiguous",
+ "MemorySpecialMemory"
+};
+
+
+/*
+ * Name: VrGetmemoryDescriptor
+ *
+ * Description:
+ * This routine returns a pointer to the next memory descriptor. If
+ * the specified memory descriptor is NULL, then a pointer to the
+ * first memory descriptor is returned. If there are no more memory
+ * descriptors, then NULL is returned.
+ *
+ * Arguments:
+ * MemoryDescriptor - Supplies a optional pointer to a memory descriptor.
+ *
+ * Return Value:
+ * If there are any more entries in the memory descriptor list, the
+ * address of the next descriptor is returned. Otherwise, NULL is
+ * returned.
+ *
+ */
+PMEMORY_DESCRIPTOR
+VrGetMemoryDescriptor(
+ IN PMEMORY_DESCRIPTOR MemoryDescriptor OPTIONAL
+ )
+{
+ PMEMORY_DESCRIPTOR P;
+ PVR_MEMORY_DESCRIPTOR Entry;
+
+ debug(VRDBG_MEM, "VrGetMemoryDescriptor(%x): ", MemoryDescriptor);
+
+ if (MemoryDescriptor == (PMEMORY_DESCRIPTOR) NULL) {
+ P = &(VrMemoryListOrig->MemoryEntry);
+ debug(VRDBG_MEM, "%x (%s %x %x)\n", P, MemoryTypeTable[P->MemoryType],
+ P->BasePage, P->PageCount);
+ return (P);
+ }
+
+ for (Entry = VrMemoryListOrig; Entry; Entry = Entry->NextEntry) {
+ if (&Entry->MemoryEntry == MemoryDescriptor) {
+ break;
+ }
+ }
+ if (Entry->NextEntry == NULL) {
+ debug(VRDBG_MEM, "NULL\n");
+ return ((PMEMORY_DESCRIPTOR) NULL);
+ } else {
+ P = &(Entry->NextEntry->MemoryEntry);
+ debug(VRDBG_MEM, "%x (%s %x %x)\n", P, MemoryTypeTable[P->MemoryType],
+ P->BasePage, P->PageCount);
+ return (P);
+ }
+}
+
+
+/*
+ * Name: VrCreateMemoryDescriptor
+ *
+ * Description:
+ * This function creates the list of memory descriptors.
+ *
+ */
+VOID
+VrCreateMemoryDescriptors(
+ VOID
+ )
+{
+ phandle ph;
+ char *regp;
+ reg *cur_reg;
+ int addr_cells, size_cells, regsize;
+ PVR_MEMORY_DESCRIPTOR pre_desc, cur_desc;
+ PVR_MEMORY_DESCRIPTOR FoundDesc;
+ ULONG proplen, cur_basepage, cur_pagecount;
+ ULONG i;
+ debug(VRDBG_MEM|VRDBG_ENTRY,
+ "VrCreateMemoryDescriptors:____________________BEGIN...\n");
+
+ //
+ // Get phandle for /memory.
+ //
+ ph = OFFinddevice("/chosen");
+ if (ph == -1) {
+ fatal("Cannot access /chosen node.\n");
+ }
+ ph = OFInstanceToPackage(get_int_prop(ph, "memory"));
+ if (ph == -1) {
+ fatal("Cannot access /memory node.\n");
+ }
+
+ //
+ // Get information of installed memory from OpenFirmware.
+ //
+ if ((proplen = OFGetproplen(ph, "reg")) <= 0) {
+ fatal("No memory reg structs. proplen = %d\n", proplen);
+ }
+ regp = malloc(proplen);
+ if (OFGetprop(ph, "reg", regp, proplen) != (long) proplen) {
+ warn("Getprop(memory.reg) return != %d\n", proplen);
+ }
+ //
+ // How big are the descriptors? How many "cells" are required to
+ // represent addresses.
+ //
+ addr_cells = get_int_prop(OFParent(ph), "#address-cells");
+ if (addr_cells == -1) {
+ addr_cells = 2;
+ }
+
+ //
+ // How many ints is an address cell?
+ //
+ size_cells = get_int_prop(OFParent(ph), "#size-cells");
+ if (size_cells == -1) {
+ size_cells = 1;
+ }
+
+ regsize = (addr_cells + size_cells) * sizeof(int);
+ debug(VRDBG_MEM, "regsize: %x, proplen: %x\n",regsize, proplen);
+
+
+ //
+ // Look at the "reg" property list for the /memory node. This list
+ // shows what memory the firmware has already "claimed" for any reason.
+ //
+ pre_desc = (PVR_MEMORY_DESCRIPTOR) &VrMemoryListOrig;
+ debug(VRDBG_MEM, "VrCreateMemoryDescriptors: Base Page Page Count\n");
+ for (i = 0; i < proplen/regsize; i++) {
+ cur_desc = new(VR_MEMORY_DESCRIPTOR);
+ cur_desc->NextEntry = NULL;
+ pre_desc->NextEntry = cur_desc;
+ cur_desc->MemoryEntry.MemoryType = MemoryFirmwareTemporary;
+ cur_reg = decode_reg( regp + (i * regsize),
+ regsize,
+ addr_cells,
+ size_cells
+ );
+ cur_desc->MemoryEntry.BasePage =
+ (cur_reg->lo >> PAGE_SHIFT) + (cur_reg->hi << (32-PAGE_SHIFT));
+
+ cur_desc->MemoryEntry.PageCount = cur_reg->size >> PAGE_SHIFT;
+ debug(VRDBG_MEM, "\t\t\t\t\t0x%x\t0x%x\n",
+ cur_desc->MemoryEntry.BasePage,cur_desc->MemoryEntry.PageCount);
+
+ pre_desc = cur_desc;
+
+ }
+
+ //
+ // Release the area for "reg" property
+ //
+ free(regp);
+
+ //
+ // Get information of available memory from OpenFirmware.
+ //
+ if ((proplen = OFGetproplen(ph, "available")) <= 0) {
+ fatal("No memory available structs. proplen = %d\n", proplen);
+ }
+ regp = malloc(proplen);
+ if (OFGetprop(ph, "available", regp, proplen) != (long) proplen) {
+ warn("Getprop(memory.available) return != %d\n", proplen);
+ }
+
+ //
+ // Search the chunk specified by each "available" memory
+ // in the installed memory. Then make the chunk MemoryFree.
+ //
+ for (i = 0; i < proplen/regsize; i++) {
+ cur_reg = decode_reg(regp + (i * regsize), regsize, 1, 1);
+ cur_basepage =
+ (cur_reg->lo >> PAGE_SHIFT) + (cur_reg->hi << (32-PAGE_SHIFT));
+
+ cur_pagecount = cur_reg->size >> PAGE_SHIFT;
+
+ FoundDesc = SearchMemoryList(cur_basepage, cur_pagecount);
+ if (FoundDesc == NULL) {
+ fatal("Available memory (0x%x, 0x%x) is not in installed memory",
+ cur_basepage, cur_pagecount);
+ }
+
+ if ((FoundDesc->MemoryEntry.BasePage == cur_basepage) &&
+ (FoundDesc->MemoryEntry.PageCount == cur_pagecount)) {
+
+ FoundDesc->MemoryEntry.MemoryType = MemoryFree;
+ } else {
+ SplitDesc(FoundDesc, cur_basepage, cur_pagecount, MemoryFree);
+ }
+ debug(VRDBG_MEM, "\t\t\t\t\t0x%x\t0x%x\n",
+ FoundDesc->MemoryEntry.BasePage, FoundDesc->MemoryEntry.PageCount);
+ }
+
+ //
+ // Release the area for "available" property
+ //
+ free(regp);
+
+ //
+ // For some memory chunks, mark specific attributes.
+ //
+ cur_desc = VrMemoryListOrig;
+ while (cur_desc != NULL) {
+ PMEMORY_DESCRIPTOR cur_mem;
+
+ cur_mem = &cur_desc->MemoryEntry;
+
+ //
+ // The loaded program must be MemoryLoadedProgram.
+ //
+
+ if ( cur_mem->BasePage == 0x600) {
+ cur_mem->MemoryType = MemoryLoadedProgram;
+ }
+
+ //
+ // The first N pages are marked Permanent.
+ //
+
+ if ( cur_mem->BasePage == 0x0) {
+ cur_mem->MemoryType = MemoryFirmwarePermanent;
+ }
+
+ //
+ // If a descriptor crosses the 8MB line, split it.
+ //
+
+ if (cur_mem->BasePage < 0x800 &&
+ (cur_mem->BasePage + cur_mem->PageCount > 0x800)) {
+
+ SplitDesc(cur_desc, cur_mem->BasePage,
+ 0x800 - cur_mem->BasePage, MemoryFree);
+ }
+
+ //
+ // Descriptors > 8MB are marked FirmwareTemporary.
+ //
+
+ if (cur_mem->MemoryType == MemoryFree && cur_mem->BasePage >= 0x800) {
+ cur_mem->MemoryType = MemoryFirmwareTemporary;
+ }
+ cur_desc = cur_desc->NextEntry;
+ }
+ debug(VRDBG_MEM|VRDBG_ENTRY,
+ "VrCreateMemoryDescriptors:____________________...END\n");
+}
+
+
+/*
+ * Name: VrMemoryInitialize
+ *
+ * Description:
+ * This function initializes the Memory entry points in the firmware
+ * transfer vector and the file table.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrMemoryInitialize(
+ VOID
+ )
+{
+ //
+ // Initialize the I/O entry points in the firmware transfer vector.
+ //
+ debug(VRDBG_ENTRY, "VrMemoryInitialize: BEGIN....\n");
+ (PARC_MEMORY_ROUTINE) SYSTEM_BLOCK->FirmwareVector[MemoryRoutine] =
+ VrGetMemoryDescriptor;
+ debug(VRDBG_ENTRY, "VrMemoryInitialize: ....END\n");
+}
+
+
+STATIC
+PVR_MEMORY_DESCRIPTOR
+SearchMemoryList(
+ ULONG CurBasePage,
+ ULONG CurPageCount
+ )
+{
+ PVR_MEMORY_DESCRIPTOR search_desc;
+
+ search_desc = VrMemoryListOrig;
+ while(search_desc != NULL) {
+ if (search_desc->MemoryEntry.BasePage <= CurBasePage
+ && search_desc->MemoryEntry.BasePage +
+ search_desc->MemoryEntry.PageCount >= CurBasePage+CurPageCount) {
+
+ return search_desc;
+ }
+ search_desc = search_desc->NextEntry;
+ }
+ return (PVR_MEMORY_DESCRIPTOR) NULL;
+}
+
+/*
+ *
+ * Routine: VOID SplitDesc(PVR_MEMORY_DESCRIPTOR, ULONG, ULONG, MEMORY_TYPE)
+ *
+ *
+ * Description:
+ * This routine is called to split a memory descriptor into two
+ pieces. The only issue is whether the left over piece is the
+ first or the second of the two pieces.
+
+ The original descriptor looks like.....
+
+ CurBasePage
+ |-----------------------PageCount-------------->|
+ ________________________________________________
+ | |
+ | Original Type (OType) |
+ | |
+ | |
+ ------------------------------------------------
+
+ The new arrangement will have pieces that are either
+
+
+ CurBasePage
+ |---------CurPageCount-------->|
+ ________________________________________________
+ | | |
+ | Original Piece, | New Piece |
+ | MemType passed in | OType |
+ | | |
+ ------------------------------------------------
+
+ OR it will look like:.....
+
+ CurBasePage
+ | |--CurPageCount->|
+ ________________________________________________
+ | | |
+ | OType, Original Descript. | New Piece |
+ | | MemType |
+ | | |
+ ------------------------------------------------
+ *
+ */
+
+STATIC
+VOID
+SplitDesc(
+ PVR_MEMORY_DESCRIPTOR MemDesc,
+ ULONG CurBasePage,
+ ULONG CurPageCount,
+ MEMORY_TYPE MemType
+ )
+{
+ PVR_MEMORY_DESCRIPTOR new_desc;
+
+ //
+ // If the descriptor passed in points the the base page passed in,
+ // then take the current descriptor and retype it the MemType, size
+ // it as CurPageCount, and then create a new descriptor to describe
+ // what's left over maintaining the original mem type.
+ //
+ if (MemDesc->MemoryEntry.BasePage == CurBasePage) {
+ new_desc = new(VR_MEMORY_DESCRIPTOR);
+ new_desc->NextEntry = MemDesc->NextEntry;
+ MemDesc->NextEntry = new_desc;
+
+ new_desc->MemoryEntry.MemoryType = MemDesc->MemoryEntry.MemoryType;
+ new_desc->MemoryEntry.BasePage =
+ MemDesc->MemoryEntry.BasePage + CurPageCount;
+
+ new_desc->MemoryEntry.PageCount =
+ MemDesc->MemoryEntry.PageCount - CurPageCount;
+
+ MemDesc->MemoryEntry.MemoryType = MemType;
+ MemDesc->MemoryEntry.BasePage = CurBasePage;
+ MemDesc->MemoryEntry.PageCount = CurPageCount;
+
+ return;
+ }
+
+ //
+ // If the base page value passed in is not the base page of the
+ // descriptor passed in, then the size and type refer to a region to
+ // carve out of the end of this descriptor rather than the beginning.
+ //
+ new_desc = new(VR_MEMORY_DESCRIPTOR);
+ new_desc->NextEntry = MemDesc->NextEntry;
+ MemDesc->NextEntry = new_desc;
+
+ new_desc->MemoryEntry.MemoryType = MemType;
+ new_desc->MemoryEntry.BasePage = CurBasePage;
+ new_desc->MemoryEntry.PageCount = CurPageCount;
+
+ MemDesc->MemoryEntry.PageCount -= CurPageCount;
+
+ if (MemDesc->MemoryEntry.BasePage + MemDesc->MemoryEntry.PageCount
+ != new_desc->MemoryEntry.BasePage) {
+ ULONG old_size = MemDesc->MemoryEntry.PageCount;
+
+ new_desc = new(VR_MEMORY_DESCRIPTOR);
+ new_desc->NextEntry = MemDesc->NextEntry->NextEntry;
+ MemDesc->NextEntry->NextEntry = new_desc;
+
+ MemDesc->MemoryEntry.PageCount =
+ MemDesc->NextEntry->MemoryEntry.BasePage -
+ MemDesc->MemoryEntry.BasePage;
+
+ new_desc->MemoryEntry.MemoryType = MemDesc->MemoryEntry.MemoryType;
+ new_desc->MemoryEntry.BasePage =
+ MemDesc->NextEntry->MemoryEntry.BasePage +
+ MemDesc->NextEntry->MemoryEntry.PageCount;
+
+ new_desc->MemoryEntry.PageCount =
+ old_size - MemDesc->MemoryEntry.PageCount;
+ }
+
+ return;
+}
+
+VOID
+DisplayMemory(VOID)
+{
+ PMEMORY_DESCRIPTOR P = NULL;
+ while ((P = VrGetMemoryDescriptor(P)) != NULL) {
+ debug(VRDBG_MEM, "MemoryType=%s, BasePage=0x%x, PageCount=0x%x\n",
+ MemoryTypeTable[P->MemoryType], P->BasePage, P->PageCount);
+ }
+}
diff --git a/private/ntos/boot/veneer/vrmisc.c b/private/ntos/boot/veneer/vrmisc.c
new file mode 100644
index 000000000..e91bd966e
--- /dev/null
+++ b/private/ntos/boot/veneer/vrmisc.c
@@ -0,0 +1,221 @@
+/*
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirePower Systems Inc.
+ *
+ * $RCSfile: vrmisc.c $
+ * $Revision: 1.10 $
+ * $Date: 1996/06/17 02:55:38 $
+ * $Locker: $
+ *
+ *
+ * Module Name:
+ * vrmisc.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 07-Sep-94 Shin Iwamoto at FirePower System Inc.
+ * Modifying the existence of L2 cache.
+ * 16-Jun-94 Shin Iwamoto at FirePower System Inc.
+ * Changed the property getting code using get_str_prop()
+ * in VrGetTime().
+ * 14-Jun-94 Shin Iwamoto at FirePower System Inc.
+ * Added a pointer to VRTime because a type mismatch happened.
+ * 19-May-94 Shin Iwamoto at FirePower System Inc.
+ * Added some logic in VrGetTime().
+ * Added some comments.
+ * 05-May-94 Shin Iwamoto at FirePower System Inc.
+ * Created.
+ *
+ */
+
+
+#include "veneer.h"
+
+//
+// Static data.
+//
+STATIC TIME_FIELDS VrTime;
+STATIC LONG StartTime; // XXXX structure
+
+
+/*
+ * Name: VrGetTime
+ *
+ * Description:
+ * This function returns a pointer to a time structure.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * Returns a pointer to a time structure. If the time infomation is
+ * valid, valid data is returned, otherwise all fields are returned
+ * as zero.
+ *
+ */
+PTIME_FIELDS
+VrGetTime(VOID)
+{
+ PTIME_FIELDS PVrTime = &VrTime; // Satisfy the compiler.
+ phandle ph;
+ ihandle ih;
+ int res[7];
+
+ //
+ // "The experienced programmer puts a known elephant in
+ // Cairo so the search will always terminate."
+ //
+ VrTime.Year = 0;
+ VrTime.Month = 0;
+ VrTime.Day = 0;
+ VrTime.Hour = 0;
+ VrTime.Minute = 0;
+ VrTime.Second = 0;
+ VrTime.Milliseconds = 0;
+ VrTime.Weekday = 0;
+
+ ph = FindNodeByType("rtc");
+ if (ph == 0) {
+ warn("VrGetTime: Could not find the RTC node.\n");
+ goto out;
+ }
+ ih = OpenPackage(ph);
+ if (ih == 0) {
+ goto out;
+ }
+ OFCallMethod(7, 2, res, "get-time", ih);
+ OFClose(ih);
+ if (res[0] != 0) {
+ goto out;
+ }
+
+ VrTime.Year = res[6];
+ VrTime.Month = res[5];
+ VrTime.Day = res[4];
+ VrTime.Hour = res[3];
+ VrTime.Minute = res[2];
+ VrTime.Second = res[1];
+
+out:
+ return (PVrTime);
+}
+
+
+/*
+ * Name: VrGetRelativeTime
+ *
+ * Description:
+ * This routine returns the time in seconds since Veneer starts.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * If the time information is valid, valid data is returned.
+ * Otherwise a zero is returned.
+ *
+ */
+ULONG
+VrGetRelativeTime( VOID )
+{
+ return OFMilliseconds()/1000;
+}
+
+
+/*
+ * Name: VrTimeInitialize
+ *
+ * Description:
+ * This function initializes the time routine addresses in the firmware
+ * transfer vector and the internal counter for the relative time.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrTimeInitialize(
+ VOID
+ )
+{
+ debug(VRDBG_ENTRY, "VrTimeInitialize BEGIN....\n");
+ //
+ // Initialize the Time routine addresses in the firmware transfer vector.
+ //
+ (PARC_GET_TIME_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetTimeRoutine] = VrGetTime;
+
+ (PARC_GET_RELATIVE_TIME_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetRelativeTimeRoutine] =
+ VrGetRelativeTime;
+ (PARC_FLUSH_ALL_CACHES_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[FlushAllCachesRoutine] =
+ VrFlushAllCaches;
+ debug(VRDBG_ENTRY, "VrTimeInitialize ....END\n");
+
+}
+
+VOID
+VrFlushAllCaches(VOID)
+{
+ ULONG start;
+ phandle ph;
+ char *regp;
+ reg *cur_reg;
+ int i, size_cells, addr_cells, proplen, regsize;
+ extern VOID HalpSweepPhysicalRangeInBothCaches(ULONG, ULONG, ULONG);
+
+ /*
+ * Flush each chunk of physical memory. Use the memory scanning
+ * code from vrmemory.c; see that file for comments.
+ */
+
+ ph = OFFinddevice("/chosen");
+ if (ph == -1) {
+ fatal("Cannot access /chosen node.\n");
+ }
+ ph = OFInstanceToPackage(get_int_prop(ph, "memory"));
+
+ if (ph == -1) {
+ fatal("Cannot access /memory node.\n");
+ }
+
+ if ((proplen = OFGetproplen(ph, "reg")) <= 0) {
+ fatal("No memory reg structs. proplen = %d\n", proplen);
+ }
+ regp = malloc(proplen);
+ if (OFGetprop(ph, "reg", regp, proplen) != (long) proplen) {
+ fatal("Getprop(memory.reg) return != %d\n", proplen);
+ }
+
+ addr_cells = get_int_prop(OFParent(ph), "#address-cells");
+ if (addr_cells == -1) {
+ addr_cells = 2;
+ }
+ size_cells = get_int_prop(OFParent(ph), "#size-cells");
+ if (size_cells == -1) {
+ size_cells = 1;
+ }
+ regsize = (addr_cells + size_cells) * sizeof(int);
+
+
+ for (i = 0; i < proplen/regsize; i++) {
+ cur_reg = decode_reg( regp + (i * regsize),
+ regsize,
+ addr_cells,
+ size_cells
+ );
+ start = cur_reg->lo >> PAGE_SHIFT;
+ start += cur_reg->hi << (32-PAGE_SHIFT);
+ HalpSweepPhysicalRangeInBothCaches(start, 0, cur_reg->size);
+ }
+
+ free(regp);
+
+}
diff --git a/private/ntos/boot/veneer/vrpehdr.c b/private/ntos/boot/veneer/vrpehdr.c
new file mode 100644
index 000000000..d8528ac55
--- /dev/null
+++ b/private/ntos/boot/veneer/vrpehdr.c
@@ -0,0 +1,138 @@
+/*++
+ *
+ * Copyright (c) 1996 FirePower Systems, Inc.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1994 FirePower Systems Inc.
+ *
+ * $RCSfile: vrpehdr.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/02/17 00:50:30 $
+ * $Locker: $
+
+Module Name:
+
+ vrpehdr.c
+
+Abstract:
+
+ These routines read and parse the Microsoft PE header.
+
+Author:
+
+ Mike Tuciarone 9-May-1994
+
+
+Revision History:
+
+--*/
+
+
+#include "veneer.h"
+
+
+
+
+#define HEADER_CHR (IMAGE_FILE_EXECUTABLE_IMAGE | \
+ IMAGE_FILE_BYTES_REVERSED_LO | \
+ IMAGE_FILE_32BIT_MACHINE | \
+ IMAGE_FILE_BYTES_REVERSED_HI)
+
+/*
+ * For some reason NT 3.5 changed the OSLoader header.
+ */
+#define HEADER_CHR_35 (IMAGE_FILE_EXECUTABLE_IMAGE | \
+ IMAGE_FILE_32BIT_MACHINE | \
+ IMAGE_FILE_LINE_NUMS_STRIPPED)
+
+void *
+load_file(ihandle bootih)
+{
+ IMAGE_FILE_HEADER FileHdr;
+ IMAGE_OPTIONAL_HEADER OptHdr;
+ IMAGE_SECTION_HEADER *SecHdr, *hdr;
+ int res, size, i;
+ PCHAR BaseAddr;
+
+ if ((res = OFRead(bootih, (char *) &FileHdr, IMAGE_SIZEOF_FILE_HEADER))
+ != IMAGE_SIZEOF_FILE_HEADER) {
+ fatal("Couldn't read entire file header: got %d\n", res);
+ }
+
+ /*
+ * Sanity check.
+ */
+ if (FileHdr.Machine != IMAGE_FILE_MACHINE_POWERPC) {
+ fatal("Wrong machine type: %x\n", FileHdr.Machine);
+ }
+#ifdef NOT
+ /*
+ * Don't bother to check the flags. They change every release anyway.
+ */
+ if ((FileHdr.Characteristics & HEADER_CHR ) != HEADER_CHR &&
+ (FileHdr.Characteristics & HEADER_CHR_35) != HEADER_CHR_35) {
+ fatal("Wrong header characteristics: %x\n",
+ FileHdr.Characteristics);
+ }
+#endif
+
+ size = FileHdr.SizeOfOptionalHeader;
+ if ((res = OFRead(bootih, (char *) &OptHdr, size)) != size) {
+ fatal("Couldn't read optional header: expect %x got %x\n",
+ size, res);
+ }
+
+ /*
+ * More sanity.
+ */
+ if (OptHdr.Magic != 0x010b) {
+ fatal("Wrong magic number in header: %x\n", OptHdr.Magic);
+ }
+
+ /*
+ * Compute image size and claim memory at specified virtual address.
+ * We assume the SizeOfImage field is sufficient.
+ */
+ BaseAddr = (PCHAR) OptHdr.ImageBase;
+ if (CLAIM(BaseAddr, OptHdr.SizeOfImage) == -1) {
+ fatal("Couldn't claim %x bytes of VM at %x\n",
+ OptHdr.SizeOfImage, BaseAddr);
+ }
+ bzero(BaseAddr, OptHdr.SizeOfImage);
+
+ /*
+ * Allocate section headers.
+ */
+ size = FileHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
+ SecHdr = (PIMAGE_SECTION_HEADER) malloc(size);
+ if ((res = OFRead(bootih, (char *) SecHdr, size)) != size) {
+ fatal("Couldn't read section headers: expect %x got %x\n",
+ size, res);
+ }
+
+ /*
+ * Loop through section headers, reading in each piece at the
+ * specified virtual address.
+ */
+ for (i = 0; i < FileHdr.NumberOfSections; ++i) {
+ hdr = &SecHdr[i];
+ debug(VRDBG_PE, "Processing section %d: %s\n", i, hdr->Name);
+ if (hdr->SizeOfRawData == 0) {
+ continue;
+ }
+ if (OFSeek(bootih, 0, hdr->PointerToRawData) == -1) {
+ fatal("seek to offset %x failed\n",
+ hdr->PointerToRawData);
+ }
+ res = OFRead(bootih,
+ (PCHAR) hdr->VirtualAddress + (ULONG) BaseAddr,
+ hdr->SizeOfRawData);
+ if ((ULONG)res != hdr->SizeOfRawData) {
+ fatal("Couldn't read data: exp %x got %x\n",
+ hdr->SizeOfRawData, res);
+ }
+ }
+ free((char *)SecHdr);
+
+ return (void *)(BaseAddr + OptHdr.AddressOfEntryPoint);
+}
diff --git a/private/ntos/boot/veneer/vrrstart.c b/private/ntos/boot/veneer/vrrstart.c
new file mode 100644
index 000000000..7d4ebc3f6
--- /dev/null
+++ b/private/ntos/boot/veneer/vrrstart.c
@@ -0,0 +1,274 @@
+/*
+ *
+ * Copyright (c) 1994 FirePower Systems Inc.
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrrstart.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/04/15 02:55:36 $
+ * $Locker: $
+ *
+ *
+ * Module Name:
+ * vrrstart.c
+ *
+ * Author:
+ * Shin Iwamoto at FirePower Systems Inc.
+ *
+ * History:
+ * 16-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * Changed the property getting code using get_str_prop()
+ * in VrGetSystemId().
+ * 14-Jun-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added the pointer to SystemId because type mismatch happened.
+ * 19-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added some comments.
+ * 13-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Added jump-logic to the restart address in VrRestart().
+ * Added VrRestartInitialize().
+ * 12-May-94 Shin Iwamoto at FirePower Systems Inc.
+ * Created.
+ *
+ */
+
+
+
+#include "veneer.h"
+
+
+//
+// Static data.
+//
+STATIC SYSTEM_ID SystemId;
+
+
+/*
+ * Name: VrEnterInteractiveMode
+ *
+ * Description:
+ * This function terminates the executing program and enters
+ * interactive mode.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrEnterInteractiveMode(
+ VOID
+ )
+{
+ (VOID)OFEnter();
+}
+
+
+/*
+ * Name: VrGetSystemId
+ *
+ * Description:
+ * This function returns a pointer to a system identification
+ * structure that contains information used to uniquely identify
+ * each system.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * The 16-byte system identification structure is returned.
+ *
+ */
+PSYSTEM_ID
+VrGetSystemId(
+ VOID
+ )
+{
+ phandle PHandle;
+ PCHAR Property;
+ PSYSTEM_ID PSystemId = &SystemId;
+
+ if ((LONG)(PHandle = OFFinddevice("/")) == -1) {
+ fatal("Veneer: cannot find the root node in Open Firmware.\n");
+ }
+
+ if ((Property = get_str_prop(PHandle, "name", NOALLOC)) == (PCHAR)NULL) {
+ fatal("Veneer: cannot get the name property for the root node.\n");
+ }
+ bcopy(Property, SystemId.VendorId, 8);
+
+ if ((Property = get_str_prop(PHandle, "id", NOALLOC)) == (PCHAR)NULL) {
+ fatal("Veneer: cannot get the name property for the root node.\n");
+ }
+ bcopy(Property, SystemId.ProductId, 8);
+
+ return PSystemId;
+}
+
+
+/*
+ * Name: VrPowerDown
+ *
+ * Description:
+ * This function is identical to the VrHalt() with the additional
+ * feature that, the power to a system is removed if the system is
+ * equipped so.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrPowerDown(VOID)
+{
+ // XXX - This must use the HALT interface; see the PPC binding.
+ OFExit();
+}
+
+
+/*
+ * Name: VrReboot
+ *
+ * Description:
+ * This function reboots the system with the same parameters used
+ * for the previous system load sequence. If the parameters cannot
+ * be reproduced, then the default system load sequence is performed.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrReboot(
+ VOID
+ )
+{
+ // XXXX
+ // Make sure that this funciton reboots the system with the same
+ // parameters used for the previous system load sequence. If the
+ // parameters cannot be reporduced, then the default system load
+ // sequence is performed.
+ (VOID)OFBoot((PCHAR)NULL);
+}
+
+
+/*
+ * Name: VrRestart
+ *
+ * Description:
+ * This function performs the equivalent of a power-on reset.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrRestart(
+ VOID
+ )
+{
+
+ PRESTART_BLOCK PRestartBlock;
+
+ //
+ // Detect the presence of a valid Restart Block
+ //
+ PRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (PRestartBlock != (PRESTART_BLOCK)NULL) {
+ if (PRestartBlock->Signature == RSTB_SIGNATURE &&
+ (PRestartBlock->Version == ARC_VERSION) &&
+ (PRestartBlock->Revision == ARC_REVISION)) {
+
+ break;
+ }
+ PRestartBlock = PRestartBlock->NextRestartBlock;
+ }
+
+ //
+ // Perform a normal power-on sequence if a valid RestartBlock
+ // is not found.
+ //
+ if (PRestartBlock == (PRESTART_BLOCK)NULL) {
+ (VOID)OFBoot((PCHAR)NULL);
+ }
+ //
+ // Reboot the system.
+ //
+
+ //
+ // Goto the RestartAddress, not return;
+ //
+ (VOID)(*(VOID (*)())(PRestartBlock->RestartAddress))();
+}
+
+
+/*
+ * Name: VrHalt
+ *
+ * Description:
+ * This function exits the program.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrHalt(
+ VOID
+ )
+{
+ (VOID)OFExit();
+}
+
+
+/*
+ * Name: VrRestartInitialize
+ *
+ * Description:
+ * This function initializes restart routine addresses in the firmware
+ * transfer vector.
+ *
+ * Arguments:
+ * None.
+ *
+ * Return Value:
+ * None.
+ *
+ */
+VOID
+VrRestartInitialize(
+ VOID
+ )
+{
+ debug(VRDBG_ENTRY, "VrRestartInitialize BEGIN....\n");
+ //
+ // Initialize Restart routine addresses in the firmware transfer vector.
+ //
+ (PARC_INTERACTIVE_MODE_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[InteractiveModeRoutine] =
+ VrEnterInteractiveMode;
+ (PARC_GET_SYSTEM_ID_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[GetSystemIdRoutine] = VrGetSystemId;
+ (PARC_POWERDOWN_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[PowerDownRoutine] = VrPowerDown;
+ (PARC_REBOOT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[RebootRoutine] = VrReboot;
+ (PARC_RESTART_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[RestartRoutine] = VrRestart;
+ (PARC_HALT_ROUTINE)
+ SYSTEM_BLOCK->FirmwareVector[HaltRoutine] = VrHalt;
+ debug(VRDBG_ENTRY, "VrRestartInitialize ....END\n");
+}
diff --git a/private/ntos/boot/veneer/vrsup.c b/private/ntos/boot/veneer/vrsup.c
new file mode 100644
index 000000000..4b067dd67
--- /dev/null
+++ b/private/ntos/boot/veneer/vrsup.c
@@ -0,0 +1,369 @@
+/*++
+ *
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ * Copyright (c) 1994 FirePower Systems, Inc.
+ *
+ * $RCSfile: vrsup.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/02/17 00:42:16 $
+ * $Locker: $
+ *
+
+
+Module Name:
+
+ vrsup.c
+
+Abstract:
+
+ A given physical device may be represented by a variety
+ of objects. More importantly, the veneer must be able to
+ translate freely between these objects.
+
+ ______________ ____________________
+ | 1275 | | ARC |
+ | | | |
+ | | | |
+ | Path | | ArcPath |
+ | \ | | / |
+ | \ | | / |
+ | \ | | / |
+ | \ | | / |
+ | \| |/ |
+ | \ / |
+ | |\ /| |
+ | | \ / | |
+ | | \ / | |
+ | | \ / | |
+ | | \ / | |
+ | | \ / | |
+ | | \ / | |
+ | Package---+-------Node | |
+ | | / \ | |
+ | | / \ | |
+ | | / \ | |
+ | | / \ | |
+ | | / \ | |
+ | | / \ | |
+ | |/ \| |
+ | / \ |
+ | /| |\ |
+ | / | | \ |
+ | / | | \ |
+ | Instance | | File Descriptor |
+ | | | |
+ |______________| |____________________|
+
+ 1275 objects include the "Package," the "Instance,"
+ and the device specifier, here simply termed the "Path."
+ ARC objects include the ARC device specifier, here the
+ "ArcPath," and the File Descriptor which does not appear
+ in this module.
+
+ The CONFIGURATION_NODE object, a.k.a. the "Node," is the
+ central data object in the veneer, and is used to translate
+ from 1275 to ARC and vice versa.
+
+ This file contains the routines which do path traversal
+ and translation for both 1275 and ARC trees. The general
+ form of the publicly accessible functions is
+
+ P<yyy> <xxx>To<yyy>(P<xxx>);
+
+ where <xxx> and <yyy> are one of
+
+ Path
+ Package
+ Instance
+ Node
+ ArcPath
+
+ and P<xxx> and P<yyy> are types <xxx> and <yyy> if
+ <xxx> and <yyy> are scalar, and pointers-to-<xxx>/<yyy>
+ if not.
+
+ This sounds a lot more confusing than it is; see below.
+
+Author:
+
+ Mike Tuciarone 9-May-1994
+--*/
+
+
+#include "veneer.h"
+
+/*
+ * Given a configuration node, traverse the Veneer Configuration tree
+ * looking for a matching component name. Call this initially with
+ * Node = RootNode. Return the matching node (if any).
+ */
+STATIC PCONFIGURATION_NODE
+DoArcPathToNode(
+ PCHAR Path,
+ PCONFIGURATION_NODE Node
+ )
+{
+ PCONFIGURATION_NODE MatchedNode;
+ CHAR *name, *cp;
+ LONG TokenLen;
+ ULONG Key = 0;
+
+ if (Node == NULL) {
+ return (0);
+ }
+
+ if (cp = index(Path, '(')) {
+ TokenLen = cp - Path;
+ cp += 1;
+ Key = atoi(cp);
+ } else {
+ TokenLen = strlen(Path);
+ }
+
+ if (Node == RootNode) {
+ Node = RootNode->Child;
+ }
+
+ name = Node->ComponentName;
+ if (!strncmp(name, Path, TokenLen) && (Key == Node->Component.Key)) {
+ /*
+ * A match! Trim off the matching component.
+ */
+ debug(VRDBG_CONF,
+ "ArcPathToNode: path '%s' matched node '%s' %x\n",
+ Path, Node->ComponentName, Node->OfPhandle);
+ cp = index(Path, ')');
+ if (cp == NULL) {
+ fatal("Malformed string: '%s'\n", Path);
+ }
+ cp += 1;
+ if (*cp == '\0') {
+ debug(VRDBG_CONF,
+ "String exhausted, returning %x\n", Node);
+ return(Node);
+ }
+ /*
+ * If this call returns non-NULL, then we had a match
+ * further down the tree. Otherwise this is the best
+ * we can do: return this node.
+ */
+ MatchedNode = DoArcPathToNode(cp, Node->Child);
+ debug(VRDBG_CONF, "ArcPathToNode('%s') returning %x\n",
+ Path, MatchedNode ? MatchedNode->OfPhandle : 0);
+ return(MatchedNode ? MatchedNode : Node);
+ }
+ if (Node->Peer) {
+ return(DoArcPathToNode(Path, Node->Peer));
+ }
+ return (0);
+}
+
+/*
+ * External entry point:
+ */
+PCONFIGURATION_NODE
+ArcPathToNode(PCHAR Path)
+{
+ return (DoArcPathToNode(Path, RootNode));
+}
+
+
+/*
+ * Create the fully-qualified ARC path to describe the argument node.
+ */
+PCHAR
+NodeToArcPath(PCONFIGURATION_NODE node)
+{
+ CHAR *oldbuf, *newbuf;
+ LONG len;
+
+ // Add 3 to each length for the key.
+ len = 1;
+ newbuf = zalloc(len);
+ do {
+ oldbuf = newbuf;
+ len += strlen(node->ComponentName) + 3;
+ newbuf = zalloc(len);
+ strcpy(newbuf, node->ComponentName);
+ strcat(newbuf, "( )");
+ newbuf[strlen(newbuf) - 2] = (char) node->Component.Key + '0';
+ strcat(newbuf, oldbuf);
+ free(oldbuf);
+ } while ((node = node->Parent) && node != RootNode);
+
+ return (newbuf);
+}
+
+
+/*
+ * Search the tree rooted at Node for a node containing the phandle Ph.
+ * NOTE: Phandles are not unique! This routine does a depth-first
+ * search to find the *deepest* node matching the phandle.
+ */
+STATIC PCONFIGURATION_NODE
+FindNodeUsingPhandle(PCONFIGURATION_NODE Node, phandle Ph)
+{
+ PCONFIGURATION_NODE Found;
+ extern int level;
+
+ debug(VRDBG_CONF, "FindNodeUsingPhandle: Node %x (%s) phandle %x\n",
+ Node, Node ? Node->ComponentName : "NULL", Ph);
+ if (Node == NULL) {
+ return (NULL);
+ }
+ /*
+ * First check to see if this node matches *and* is a wildcard.
+ * If so, return immediately.
+ */
+ if (Node->OfPhandle == Ph && Node->Wildcard) {
+ debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
+ return (Node);
+ }
+ /*
+ * Check descendants, since the terminal node may be a child of
+ * this one. See the comments in add_new_child() in vrtree.c.
+ */
+ level++;
+ Found = FindNodeUsingPhandle(Node->Child, Ph);
+ level--;
+ if (Found) {
+ debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
+ return (Found);
+ }
+ if (Node->OfPhandle == Ph) {
+ debug(VRDBG_CONF, "FindNodeUsingPhandle: return %x\n", Node);
+ return (Node);
+ }
+ return (FindNodeUsingPhandle(Node->Peer, Ph));
+}
+
+PCONFIGURATION_NODE
+PackageToNode(phandle ph)
+{
+ return (FindNodeUsingPhandle(RootNode, ph));
+}
+
+PCONFIGURATION_NODE
+PathToNode(PCHAR path)
+{
+ PCONFIGURATION_NODE node, tmpnode;
+ phandle ph;
+ PCHAR cp;
+
+ ph = OFFinddevice(path);
+ node = FindNodeUsingPhandle(RootNode, ph);
+ if (node->Wildcard) {
+ // trim off final address
+ while ((cp = index(path, '@')) != NULL) {
+ path = cp + 1;
+ }
+ // XXX run decode-unit on it
+ // XXX search peers for match using wildcard criteria
+ if ((tmpnode = FindNodeUsingPhandle(node->Child, ph)) != NULL) {
+ return (tmpnode);
+ }
+ }
+ return (node);
+}
+
+PCONFIGURATION_NODE
+InstanceToNode(ihandle ih)
+{
+ char buf[1024];
+
+ OFInstanceToPath(ih, buf, 1024);
+ return (PathToNode(buf));
+}
+
+phandle
+NodeToPackage(PCONFIGURATION_NODE node)
+{
+ return (node->OfPhandle); // "It's a gift to be simple..."
+}
+
+PCHAR
+NodeToPath(PCONFIGURATION_NODE node)
+{
+ phandle ph = NodeToPackage(node);
+ int len;
+ char *bufp;
+
+ //
+ // Translate the device name into the device path for Open Firmware.
+ // Add 1 to the reported length to account for the null terminator.
+ // (See IEEE 1275-1994, Sec. 6.3.2.2.)
+ //
+ len = OFPackageToPath(ph, (char *)0, 0) + 1;
+ bufp = (char *) zalloc(len);
+ (VOID) OFPackageToPath(ph, bufp, len);
+ debug(VRDBG_CONF, "NodeToPath found '%s'\n", bufp);
+
+ if (node->Wildcard) {
+ char *newp;
+
+ while (node->Parent->Wildcard) {
+ node = node->Parent;
+ }
+ // XXX Generate AddrPath by running encode-unit
+ // XXX on wildcard criteria
+ len += strlen(node->WildcardAddrPath);
+ newp = (char *) zalloc(len);
+ strcpy(newp, bufp);
+ free(bufp);
+ bufp = newp;
+ debug(VRDBG_CONF, "NodeToPath adding '%s'\n",
+ node->WildcardAddrPath);
+ strcat(bufp, node->WildcardAddrPath);
+ }
+ debug(VRDBG_CONF, "NodeToPath returning '%s'\n", bufp);
+ return (bufp);
+}
+
+/*
+ * This routine is hopelessly naive. See VrOpen() for a version
+ * that's been around.
+ */
+ihandle
+NodeToInstance(PCONFIGURATION_NODE node)
+{
+ char *path = NodeToPath(node);
+ ihandle ih = OFOpen(path);
+
+ free(path);
+ return (ih);
+}
+
+STATIC phandle
+DoFindNodeByType(char *type, phandle ph)
+{
+ phandle res;
+
+ if (ph == 0) {
+ return(0);
+ }
+ if (strcmp(get_str_prop(ph, "device_type", NOALLOC), type) == 0) {
+ return(ph);
+ }
+ res = DoFindNodeByType(type, OFChild(ph));
+ if (res != 0) {
+ return(res);
+ }
+ return(DoFindNodeByType(type, OFPeer(ph)));
+}
+
+phandle
+FindNodeByType(char *type)
+{
+ return(DoFindNodeByType(type, OFPeer(0)));
+}
+
+ihandle
+OpenPackage(phandle ph)
+{
+ char buf[256];
+
+ (void) OFPackageToPath(ph, buf, 256);
+ return (OFOpen(buf));
+}
+
diff --git a/private/ntos/boot/veneer/vrtree.c b/private/ntos/boot/veneer/vrtree.c
new file mode 100644
index 000000000..9d33fd651
--- /dev/null
+++ b/private/ntos/boot/veneer/vrtree.c
@@ -0,0 +1,2012 @@
+/*
+ * Copyright (c) 1995,1996 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrtree.c $
+ * $Revision: 1.51 $
+ * $Date: 1996/06/19 23:13:29 $
+ * $Locker: $
+ *
+ *
+ */
+
+#include "veneer.h"
+#include "vrtree.h"
+
+extern CHAR *VeneerVersion();
+
+/*
+ * This table contains some rudimentary plug-n-play-style mappings
+ * to assist in assigning the proper Identifiers to device nodes.
+ */
+static struct pnp_info {
+ unsigned int port;
+ char *id;
+} pnp_data[] = {
+ { 0x278, "LPT3" },
+ { 0x2bc, "LPT4" },
+ { 0x2e8, "COM4" },
+ { 0x2f8, "COM2" },
+ { 0x378, "LPT2" },
+ { 0x3bc, "LPT1" },
+ { 0x3e8, "COM3" },
+ { 0x3f8, "COM1" },
+ { 0x000, "Tooch did this." }
+};
+
+
+CONFIGURATION_NODE *RootNode;
+STATIC CONFIGURATION_NODE *DisplayNode = 0;
+
+STATIC int convert_node(CONFIGURATION_NODE *);
+STATIC CONFIGURATION_NODE *convert_controller(CONFIGURATION_NODE *);
+STATIC CONFIGURATION_NODE *add_new_child(
+ CONFIGURATION_NODE *, char *, CONFIGURATION_CLASS, CONFIGURATION_TYPE);
+STATIC int convert_name(CONFIGURATION_NODE *);
+STATIC VOID convert_config(CONFIGURATION_NODE *);
+STATIC VOID convert_cache(PCONFIGURATION_NODE);
+STATIC int convert_PCI_device(PCONFIGURATION_NODE);
+STATIC CONFIGURATION_NODE *convert_SCSI_device(PCONFIGURATION_NODE);
+STATIC CONFIGURATION_NODE *convert_IDE_device(PCONFIGURATION_NODE);
+STATIC VOID convert_system_node(PCONFIGURATION_NODE);
+STATIC VOID update_display_node(PCONFIGURATION_NODE);
+STATIC VOID configure_pci_node(reg *, PCONFIGURATION_NODE );
+
+STATIC int default_interrupt_level = 0;
+STATIC int level_equals_vector = FALSE;
+STATIC int default_interrupt_affinity = -1;
+STATIC int default_affinity = -1;
+STATIC int init_key_array[64];
+STATIC int *key_array = init_key_array;
+
+/*
+ * Traverse the OF tree. For each node, figure out what it corresponds
+ * to in an ARC tree and construct the Component and resource
+ * description data structures. Call this initially with node = 0
+ * so peer() finds the root node. See 6.3.2.2.
+ *
+ * At each node, build a CONFIGURATION_NODE and attempt to convert the
+ * node to an ARC component. If this conversion fails, free the
+ * CONFIGURATION_NODE and move on, continuing to pass "here." Otherwise
+ * move on, and pass "here" = "newlink." This way unconverted nodes
+ * are pruned out of the tree.
+ */
+
+void
+walk_obp(
+ phandle ph,
+ CONFIGURATION_NODE *here,
+ CONFIGURATION_NODE *parent,
+ CONFIGURATION_NODE *peer)
+{
+ phandle newph;
+ CONFIGURATION_NODE *newlink;
+ int *saved_key_array;
+ extern int level; // for debug output
+
+ //VRASSERT((parent) || ((parent == 0) && (here == 0) && (peer == 0)));
+ debug(VRDBG_TREE, "\n");
+ debug(VRDBG_TREE, "walk_obp: phandle 0x%x (%d)\n", ph, level);
+ debug(VRDBG_TREE, "walk_obp:\there 0x%x parent 0x%x peer 0x%x\n",
+ here, parent, peer);
+
+ if (newph = OFChild(ph)) {
+ //
+ // Here we descend to a new level of the tree. Increment "level"
+ // so that debugging printouts reflect the level of the tree,
+ // and allocate a new "key_array" since counts reset at each
+ // level of the tree. See convert_node() for the use of
+ // key_array.
+ //
+ //
+ level++;
+ saved_key_array = key_array;
+ key_array = (int *) zalloc(64 * sizeof(int)); //"Enough" slots.
+ newlink = new(CONFIGURATION_NODE);
+ newlink->OfPhandle = newph;
+ debug(VRDBG_TREE, "walk_obp:\tNew Child node: 0x%x\n", newlink);
+
+ //
+ // If there's already an ARC Node "HERE", then set the newlink's
+ // parent to point to the node "HERE".
+ //
+ if (here) {
+ newlink->Parent = here;
+ } else {
+ newlink->Parent = parent;
+ }
+ if (convert_node(newlink)) {
+ if (here) {
+ if (here->Child == 0) {
+ here->Child = newlink;
+ walk_obp(newph, newlink, here, 0);
+ } else {
+ CONFIGURATION_NODE *tmplink;
+ debug(VRDBG_TREE, "walk_obp: newlink = here->Child(0x%x)\n",
+ here->Child);
+ tmplink = here->Child;
+ while (tmplink->Peer) {
+ tmplink = tmplink->Peer;
+ }
+
+ tmplink->Peer = newlink;
+ VRDBG(VRDBG_TREE, vr_dump_config_node(tmplink));
+ walk_obp(newph, newlink, here, 0);
+ }
+ } else if (peer) {
+ newlink->Peer = peer->Peer;
+ peer->Peer = newlink;
+ walk_obp(newph, newlink, parent, newlink);
+ while (peer->Peer) {
+ peer = peer->Peer;
+ }
+ } else if (parent) {
+ newlink->Peer = parent->Child;
+ parent->Child = newlink;
+ walk_obp(newph, newlink, here, 0);
+ peer = newlink;
+ while (peer->Peer) {
+ peer = peer->Peer;
+ }
+ }
+ } else {
+ debug(VRDBG_TREE, "walk_obp: FREE CHILD NODE 0x%x\n", newlink);
+ free((char *)newlink);
+ if (here) {
+ walk_obp(newph, 0, here, 0);
+ } else {
+ walk_obp(newph, 0, parent, peer);
+ }
+ }
+ //
+ // Ascend: restore level and key_array.
+ //
+ level--;
+ key_array = saved_key_array;
+ }
+
+ if (newph = OFPeer(ph)) {
+ newlink = new(CONFIGURATION_NODE);
+ debug(VRDBG_TREE, "walk_obp:\tnew Peer node: 0x%x\n", newlink);
+ if (ph == 0) {
+ RootNode = newlink;
+ }
+ newlink->OfPhandle = newph;
+ newlink->Parent = parent;
+ if (convert_node(newlink)) {
+ if (here) {
+ if (here->Peer == 0) {
+ here->Peer = newlink;
+ } else {
+ CONFIGURATION_NODE *tmplink;
+ debug(VRDBG_TREE, "walk_obp: newlink = here->Peer(0x%x)\n",
+ here->Peer);
+ tmplink = here->Peer;
+ while (tmplink->Peer) {
+ tmplink = tmplink->Peer;
+ }
+ tmplink->Peer = newlink;
+ VRDBG(VRDBG_TREE, vr_dump_config_node(tmplink));
+ }
+ } else {
+ if (peer) {
+ newlink->Peer = peer->Peer;
+ peer->Peer = newlink;
+ } else {
+ if (parent) {
+ newlink->Peer = parent->Child;
+ parent->Child = newlink;
+ }
+ }
+ }
+ walk_obp(newph, newlink, parent, newlink);
+ } else {
+ debug(VRDBG_TREE, "walk_obp: FREE PEER NODE 0x%x\n", newlink);
+ free((char *)newlink);
+ if (here) {
+ walk_obp(newph, 0, parent, here);
+ } else {
+ walk_obp(newph, 0, parent, peer);
+ }
+ }
+ }
+ debug(VRDBG_TREE, "walk_obp =====================> exit(%d)\n",level);
+}
+
+STATIC int
+convert_node(CONFIGURATION_NODE *node)
+{
+ phandle ph = node->OfPhandle;
+ PCONFIGURATION_COMPONENT Component = &node->Component;
+ PCHAR arcid;
+ LONG key=-1;
+
+ debug(VRDBG_TREE, "convert_node: node(0x%x) Begin ....\n", node);
+ node->ComponentName = get_str_prop(ph, "name", ALLOC);
+ if (node->ComponentName == 0) {
+ debug(VRDBG_TREE, "convert_node: NULL ComponentName. return FALSE\n");
+ return FALSE;
+ }
+ if (convert_name(node) == 0) {
+ debug(VRDBG_TREE, "convert_node: convert_name returned 0...\n", node);
+ return FALSE;
+ }
+ Component->Revision = ARC_REVISION;
+ Component->Version = ARC_VERSION;
+ Component->AffinityMask = default_affinity;
+
+ switch(Component->Class) {
+ case ProcessorClass:
+ break;
+ case CacheClass:
+ convert_cache(node);
+ break;
+
+ case ControllerClass:
+ Component->Key = key_array[Component->Type]++;
+ if((node = convert_controller(node)) == 0 ) {
+ debug(VRDBG_TEST|VRDBG_TREE,
+ "Convert_node: failed convert_controller, return FALSE\n");
+ return(FALSE);
+ }
+ convert_config(node);
+ break;
+
+ default:
+ Component->Key = key_array[Component->Type]++;
+ convert_config(node);
+ break;
+ }
+
+ if (arcid = get_str_prop(ph, "arc-identifier", ALLOC)) {
+ node->Component.Identifier = arcid;
+ node->Component.IdentifierLength = strlen(arcid) + 1;
+ }
+
+ if ((key = get_int_prop(ph, "arc-key")) != -1) {
+ node->Component.Key = key;
+ }
+ debug(VRDBG_TREE|VRDBG_ENTRY,
+ "convert_node: ... returning true\n");
+ return(TRUE);
+}
+
+STATIC int
+convert_name(CONFIGURATION_NODE *node)
+{
+ char *name = node->ComponentName;
+ char *type = get_str_prop(node->OfPhandle, "device_type", NOALLOC);
+ char **id = &node->Component.Identifier;
+ char *cp, *String=0;
+ int result = 1;
+ static int ncpus = 0;
+
+ //
+ // The conversion is based upon device_type, or if that fails,
+ // name. As a first approximation the ARC node's Identifier, if
+ // converted, is set to the OFW node's name property.
+ // This is OK, as later in the process the "arc-identifier"
+ // property can override the Identifier set here. See above.
+ //
+
+ debug(VRDBG_TREE, "convert_name: node(0x%x) is type %s \n",
+ node, TypeNames[node->Component.Type]);
+ *id = name;
+ if (cp = index(name, ',')) {
+ *cp = '-';
+ }
+
+ //
+ // If Parent == 0, we can assume this is the root node.
+ //
+ if (node->Parent == 0) {
+ node->Component.Class = SystemClass;
+ node->Component.Type = ArcSystem;
+
+ //
+ // OFW, name is Company, Model
+ //
+ String = get_str_prop(node->OfPhandle, "name", ALLOC);
+ node->Component.Identifier = index(String, ',');
+ if (node->Component.Identifier == NULL) {
+ node->Component.Identifier = String;
+ } else {
+ node->Component.Identifier++;
+ }
+
+ debug(VRDBG_TEST, "convert_name: node %x (%s)", node, name);
+ debug(VRDBG_TEST, "convert_name: OFW String (%s)\n", String);
+ debug(VRDBG_TEST, "convert_name: Identifier (%s)\n",
+ node->Component.Identifier);
+ goto found;
+ }
+
+ if (type == 0) {
+ goto just_name;
+ }
+
+ //
+ // First try to match on device-type.
+ // This is enough in many cases.
+ //
+ if (strcmp(type, "cpu") == 0) {
+ node->Component.Class = ProcessorClass;
+ node->Component.Type = CentralProcessor;
+ node->Component.Key = get_int_prop(node->OfPhandle, "reg");
+ if (node->Component.Key == -1) {
+ node->Component.Key = ncpus++;
+ }
+ cp = index(name, '-') + 1;
+ *id = (char *) zalloc(13);
+ strcpy(*id, "PowerPC(");
+ strcat(*id, cp);
+ strcat(*id, ")");
+ if (get_int_prop(node->OfPhandle, "i-cache-size")) {
+ convert_cache(add_new_child(node,
+ "cache", CacheClass, PrimaryIcache));
+ }
+
+ //
+ // The following block is to support old FirePower ROMs.
+ // If version 510 ROMs are ever desupported, this block
+ // can be deleted.
+ //
+
+ if (strcmp(
+ get_str_prop(OFParent(node->OfPhandle), "name", NOALLOC),
+ "cpus") != 0) {
+
+ //
+ // This is a 510 rom: it builds a single processor
+ // node even if it's an MP machine. We need to
+ // probe and report all CPUs ourselves.
+ // Since we know 501-rom-equipped machines have
+ // 1 or 2 processors, the job isn't that bad:
+ // we look at mailbox[1] and see if the contents
+ // are equal to "processor ready" (1). If so,
+ // we are dual-proc.
+ //
+
+ PULONG mbox = (PULONG) 0x2f88;
+ CONFIGURATION_NODE *peer;
+
+ if (*mbox == 1) {
+ peer = new(CONFIGURATION_NODE);
+ bcopy((PCHAR) node, (PCHAR) peer, sizeof(CONFIGURATION_NODE));
+ node->Peer = peer;
+ peer->Component.Revision = ARC_REVISION;
+ peer->Component.Version = ARC_VERSION;
+ peer->Component.Key = ncpus++;
+ peer->Component.AffinityMask = 1 << peer->Component.Key;
+ peer->Child = 0;
+ peer->Component.IdentifierLength =
+ strlen(peer->Component.Identifier) + 1;
+ convert_cache(add_new_child(peer,
+ "cache", CacheClass, PrimaryIcache));
+ }
+ }
+
+ goto found;
+
+ } else if (strcmp(type, "cache") == 0) {
+ //
+ // What does the cache architecture of the system
+ // look like? OF reports processor caches in the cpu node,
+ // so that case is handled above. This must be a discrete
+ // off-chip cache of some kind. Is it bound to a particular
+ // processor, or is it a system-wide cache, or what?
+ //
+ // PReP machines call for a "transparent" Level-2 cache.
+ // Currently, these should be reported to NT as children
+ // of the root node--thus this code. IT IS CRUCIAL that
+ // this routine return FALSE, because we want to explicitly
+ // build a child of the root node, and we do NOT want to
+ // allow a node to be built in our present location.
+ //
+ // XXX - This may need to be re-examined in a future release
+ // as system architectures develop.
+ //
+
+ PCONFIGURATION_NODE newnode;
+
+ newnode = add_new_child(RootNode, "cache", CacheClass, SecondaryCache);
+ newnode->OfPhandle = node->OfPhandle;
+ convert_cache(newnode);
+ debug(VRDBG_TREE,"convert_node: node %s (0x%x) has new parent: ROOT.\n",
+ newnode->ComponentName, newnode);
+ return (0);
+
+ } else if (strcmp(type, "pci") == 0) {
+ node->Component.Class = AdapterClass;
+ node->Component.Type = MultiFunctionAdapter;
+ node->ComponentName = "multi";
+ *id = "PCI";
+ goto found;
+
+ } else if (strcmp(type, "isa") == 0) {
+ node->Component.Class = AdapterClass;
+ node->Component.Type = MultiFunctionAdapter;
+ node->ComponentName = "multi";
+ *id = "ISA";
+ goto found;
+
+ } else if (strncmp(type, "scsi", 4) == 0) {
+ node->Component.Class = AdapterClass;
+ node->Component.Type = ScsiAdapter;
+ node->ComponentName = "scsi";
+ String = get_str_prop(node->OfPhandle, "model", NOALLOC);
+ debug(VRDBG_TEST, "String(name)is ...%s:", String);
+ *id = (char *) zalloc(16);
+ if(strcmp(String, "NCR,53C810") == 0) {
+ *id = "NCRC810";
+ debug(VRDBG_TEST|VRDBG_SCSI,
+ "nodeID =......%s:\n", node->Component.Identifier);
+ goto found;
+ }
+ if(strcmp(String, "AMD 53C794") == 0) {
+ *id = "AMD53C974";
+ debug(VRDBG_TEST|VRDBG_SCSI,
+ "nodeID =......%s:\n", node->Component.Identifier);
+ goto found;
+ }
+ if (strncmp(String, "ADPT,AIC-78",11) == 0) {
+ *id = "AIC78XX";
+ debug(VRDBG_TEST|VRDBG_SCSI,
+ "nodeID =......%s:\n", node->Component.Identifier);
+ goto found;
+ }
+
+ *id = "UNKNOWN SCSI";
+ goto found;
+
+ } else if (strcmp(type, "ide") == 0) {
+
+ node->Component.Class = AdapterClass;
+ node->Component.Type = ScsiAdapter;
+ node->ComponentName = "scsi";
+ node->Component.Flags.Input = 1;
+ node->Component.Flags.Output = 1;
+ *id = "IDE";
+ goto found;
+
+ //
+ // Don't change the names on controllers yet. They all
+ // get treated again in convert_controller() to build
+ // their child peripheral nodes, etc. Leave the current
+ // names intact so we can distinguish between e.g.
+ // hard disk and floppy.
+ //
+ } else
+ if (strcmp(type, "block") == 0) {
+ node->Component.Class = ControllerClass;
+ if (strcmp(name, "disk") == 0) {
+ node->Component.Type = DiskController;
+ } else
+ if (strcmp(name, "floppy") == 0) {
+ node->Component.Type = DiskController;
+ } else
+ if (strcmp(name, "cdrom") == 0) {
+ node->Component.Type = CdromController;
+ } else
+ if (strcmp(name, "worm") == 0) {
+ node->Component.Type = WormController;
+ } else {
+ node->Component.Type = OtherController;
+ }
+ goto found;
+
+ } else if (strcmp(type, "byte") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = TapeController;
+ goto found;
+
+ } else if (strcmp(type, "display") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = DisplayController;
+ String = get_str_prop(node->OfPhandle, "model", ALLOC);
+ if (String == NULL) {
+ String = get_str_prop(node->OfPhandle, "name", ALLOC);
+ }
+ if (strcmp(String,"FirePower,Powerized_Display" ) == 0) {
+ node->Component.Identifier = "Powerized Graphics";
+ } else {
+ node->Component.Identifier = capitalize(String);
+ }
+ if (String == NULL) {
+ node->Component.Identifier = "VGA";
+ }
+
+ update_display_node(node);
+
+ goto found;
+
+ } else if (strcmp(type, "network") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = NetworkController;
+
+ //
+ // The stuff that follows is legacy support.
+ // See the comments for "I8042PRT" below.
+ //
+ String = get_str_prop(node->OfPhandle, "name", NOALLOC);
+ debug(VRDBG_TEST, "NetWork String(name)is ...%s:", String);
+ *id = (char *) zalloc(16);
+ if(strcmp(String, "pci1011,2") == 0) {
+ *id = "DC21x4";
+ goto found;
+ }
+ if(strcmp(String, "AMD,79c970") == 0) {
+ *id = "AMD79C970";
+ goto found;
+ }
+ *id = "UNKNOWN NETWORK";
+ goto found;
+
+ } else if (strcmp(type, "serial") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = SerialController;
+ goto found;
+
+ } else if (strcmp(type, "parallel") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = ParallelController;
+ goto found;
+
+ //
+ // For both keyboard and mouse below, the Identifier really
+ // should come from an "arc-identifier" property. Alas,
+ // there are machines in the field with ROM versions that
+ // don't have the arc-identifier property, so this legacy
+ // code will have to stay here forever.
+ //
+
+ } else if (strcmp(type, "keyboard") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = KeyboardController;
+ *id = get_str_prop(OFParent(node->OfPhandle), "name", ALLOC);
+ if (strcmp(*id, "8042") == 0) {
+ free(*id);
+ *id = "I8042PRT";
+ }
+ goto found;
+
+ } else if (strcmp(type, "mouse") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = PointerController;
+ *id = get_str_prop(OFParent(node->OfPhandle), "name", ALLOC);
+ if (strcmp(*id, "8042") == 0) {
+ free(*id);
+ *id = "I8042PRT";
+ }
+ goto found;
+ }
+
+just_name:
+
+ //
+ // Device-type wasn't enough. We'll try matching
+ // on name now.
+ //
+ if (strcmp(name, "audio") == 0) {
+ node->Component.Class = ControllerClass;
+ node->Component.Type = AudioController;
+ goto found;
+
+ } else if (strcmp(name, "memory") == 0) {
+ node->Component.Class = MemoryClass;
+ node->Component.Type = SystemMemory;
+ //
+ // "memory" nodes have two properties of interest:
+ // a "reg" prop which describes actual installed memory,
+ // and an "available" prop which describes the memory
+ // that hasn't been allocated. We'll pick up the
+ // reg prop later, in convert_config().
+ //
+ goto found;
+
+ } else if (strcmp(node->Parent->Component.Identifier, "PCI") == 0) {
+ //
+ // This is presumably a PCI expansion card, but without
+ // an FCode expansion ROM.
+ //
+ if (convert_PCI_device(node) == 0) {
+ result = 0;
+ }
+ goto found;
+
+ } else {
+ //
+ // Else what?
+ //
+ debug(VRDBG_TREE, "convert_name: node '%s' (0x%x) is unmatched!\n",
+ name, node);
+ return (0);
+ }
+found:
+ //
+ // NOTE: the IdentifierLength *includes* the null terminator.
+ //
+
+ if (*id) {
+ if (*id == name) {
+ char *newid = zalloc(strlen(*id) + 1);
+ strcpy(newid, *id);
+ *id = newid;
+ }
+ node->Component.IdentifierLength =
+ strlen(*id) + 1;
+ }
+ debug(VRDBG_TREE,
+ "convert_name: node %s (%x) type '%s' is Class %s Type %s ID: %s\n",
+ name, node, type ? type : "",
+ ClassNames[node->Component.Class], TypeNames[node->Component.Type],
+ node->Component.IdentifierLength ? node->Component.Identifier : "");
+ return (result);
+}
+
+STATIC CONFIGURATION_NODE *
+convert_controller(CONFIGURATION_NODE *node)
+{
+ phandle ph = node->OfPhandle;
+ PCONFIGURATION_COMPONENT Component = &node->Component;
+ char *name = node->ComponentName;
+
+ debug(VRDBG_TREE, "convert_controller: node(0x%x) is type %s \n",
+ node, TypeNames[node->Component.Type]);
+ if (OFChild(ph)) {
+ debug(VRDBG_TREE, "Controller node %x '%s' already has a child (%s)!\n",
+ Component, name,get_str_prop(OFChild(ph), "name", NOALLOC));
+ VRDBG(VRDBG_TREE, vr_dump_config_node(node));
+ return(0);
+ }
+
+ switch (Component->Type) {
+
+ case DiskController:
+ if (strcmp(name, "disk") == 0) {
+ (void) add_new_child(node, "rdisk",
+ PeripheralClass, DiskPeripheral);
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ } else if (strcmp(name, "floppy") == 0) {
+ (void) add_new_child(node, "fdisk",
+ PeripheralClass, FloppyDiskPeripheral);
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ node->Child->Component.Flags.Removable = 1;
+ } else
+ warn("What is this disk controller '%s'?\n", name);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ break;
+
+ case TapeController:
+ node->ComponentName = "tape";
+ (void) add_new_child(node, "tape",
+ PeripheralClass, TapePeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ node->Child->Component.Flags.Removable = 1;
+ break;
+
+ case CdromController:
+ node->ComponentName = "cdrom";
+ (void) add_new_child(node, "fdisk",
+ PeripheralClass, FloppyDiskPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.ReadOnly = 1;
+ Component->Flags.Removable = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.ReadOnly = 1;
+ node->Child->Component.Flags.Removable = 1;
+ break;
+
+ case WormController:
+ node->ComponentName = "worm";
+ (void) add_new_child(node, "rdisk",
+ PeripheralClass, DiskPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ node->Child->Component.Flags.Removable = 1;
+ break;
+
+ case SerialController:
+ node->ComponentName = "serial";
+ (void) add_new_child(node, "line",
+ PeripheralClass, LinePeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ Component->Flags.ConsoleIn = 1;
+ Component->Flags.ConsoleOut = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ node->Child->Component.Flags.ConsoleIn = 1;
+ node->Child->Component.Flags.ConsoleOut = 1;
+ break;
+
+ case NetworkController:
+ node->ComponentName = "net";
+ (void) add_new_child(node, "network",
+ PeripheralClass, NetworkPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ break;
+
+ case DisplayController:
+ node->ComponentName = "video";
+ (void) add_new_child(node, "monitor",
+ PeripheralClass, MonitorPeripheral);
+ Component->Flags.Output = 1;
+ Component->Flags.ConsoleOut = 1;
+ node->Child->Component.Identifier = "1024x768";
+ node->Child->Component.IdentifierLength = 9;
+ node->Child->Component.Flags.Output = 1;
+ node->Child->Component.Flags.ConsoleOut = 1;
+ break;
+
+ case ParallelController:
+ node->ComponentName = "par";
+ (void) add_new_child(node, "print",
+ PeripheralClass, PrinterPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ break;
+
+ case PointerController:
+ node->ComponentName = "point";
+ (void) add_new_child(node, "pointer",
+ PeripheralClass, PointerPeripheral);
+ Component->Flags.Input = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Identifier = MOUSE_IDENTIFIER;
+ node->Child->Component.IdentifierLength =
+ strlen(MOUSE_IDENTIFIER) + 1;
+ break;
+
+ case KeyboardController:
+ node->ComponentName = "key";
+ (void) add_new_child(node, "keyboard",
+ PeripheralClass, KeyboardPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.ConsoleIn = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.ConsoleIn = 1;
+ node->Child->Component.Identifier = KBD_IDENTIFIER;
+ node->Child->Component.IdentifierLength =
+ strlen(KBD_IDENTIFIER) + 1;
+ break;
+
+ case AudioController:
+ node->ComponentName = "other";
+ (void) add_new_child(node, "other",
+ PeripheralClass, OtherPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ break;
+
+ case OtherController:
+ node->ComponentName = "other";
+ (void) add_new_child(node, "other",
+ PeripheralClass, OtherPeripheral);
+ Component->Flags.Input = 1;
+ Component->Flags.Output = 1;
+ node->Child->Component.Flags.Input = 1;
+ node->Child->Component.Flags.Output = 1;
+ break;
+
+ default:
+ warn("Unknown controller class %d type %d\n",
+ Component->Class, Component->Type);
+ break;
+ }
+ //
+ // NOTE: the IdentifierLength *includes* the null terminator.
+ //
+ if (node->Component.Identifier) {
+ node->Component.IdentifierLength =
+ strlen(node->Component.Identifier) + 1;
+ }
+
+ debug(VRDBG_TREE, "convert_controller: node %x has parent %x of Type %s\n",
+ node, node->Parent, TypeNames[node->Parent->Component.Type]);
+
+ //
+ // Finally, check to see if this is a child of a ScsiAdapter.
+ // If it is, we may have to probe the bus.
+ //
+
+ if (node->Parent->Component.Type == ScsiAdapter) {
+ if (strcmp(node->Parent->Component.Identifier, "IDE") == 0) {
+ return (convert_IDE_device(node));
+ } else {
+ return (convert_SCSI_device(node));
+ }
+ }
+
+ return (node);
+}
+
+/*
+ * We found a leaf node. In classical OF this would be sufficient; i.e.
+ * this node would contain the methods to drive the device and the properties
+ * that describe the device. But in the ARC world, this node corresponds
+ * to a ControllerClass Component, which is expected to have a PeripheralClass
+ * Component that describes the actual device.
+ * In this function we take an existing "Controller" node and add a
+ * "Peripheral" node as a child.
+ */
+STATIC CONFIGURATION_NODE *
+add_new_child(
+ CONFIGURATION_NODE *parent,
+ char *name,
+ CONFIGURATION_CLASS class,
+ CONFIGURATION_TYPE type
+ )
+{
+ PCONFIGURATION_NODE child;
+ PCONFIGURATION_COMPONENT Component;
+
+ debug(VRDBG_TREE,
+ "add_new_child: parent %s(0x%x) will get child %s Type %s\n",
+ parent->ComponentName, parent, name, TypeNames[type]);
+ child = new(CONFIGURATION_NODE);
+ child->Parent = parent;
+ debug(VRDBG_TREE, "add_new_child: add child (0x%x) to node 0x%x\n",
+ child, child->Parent);
+ if (parent->Child != NULL) {
+ PCONFIGURATION_NODE node = parent->Child;
+ while (node->Peer) {
+ node = node->Peer;
+ }
+ node->Peer = child;
+ } else {
+ parent->Child = child;
+ }
+ child->ComponentName = name;
+ child->OfPhandle = parent->OfPhandle;
+ Component = &child->Component;
+ Component->Class = class;
+ Component->Type = type;
+ Component->Revision = ARC_REVISION;
+ Component->Version = ARC_VERSION;
+ Component->AffinityMask = default_affinity;
+ Component->Key = key_array[Component->Type]++;
+ VRDBG(VRDBG_TREE, vr_dump_config_node(child));
+
+ return (child);
+}
+
+/*
+ * A PCI device without an FCode ROM may yet have enough useful
+ * properties encoded in configuration space to make a reasonable
+ * guess about its device type, etc.
+ */
+STATIC int
+convert_PCI_device(PCONFIGURATION_NODE node)
+{
+ phandle ph = node->OfPhandle;
+ int class_code, base_class, sub_class, prog_class;
+
+ debug(VRDBG_TREE, "Converting PCI device '%s'\n", node->ComponentName);
+ class_code = get_int_prop(ph, "class-code");
+ debug(VRDBG_TREE, "PCI node class = %x\n", class_code);
+ if (class_code == -1) {
+ /* Hopeless */
+ return (0);
+ }
+ base_class = (class_code >> 16) & 0xff;
+ sub_class = (class_code >> 8) & 0xff;
+ prog_class = class_code & 0xff;
+
+ switch (base_class) {
+ case 0:
+ node->Component.Class = ControllerClass;
+ if (sub_class == 1 && prog_class == 0) {
+ node->Component.Type = DisplayController;
+ update_display_node(node);
+ } else {
+ node->Component.Type = OtherController;
+ }
+ goto ok;
+
+ case 1:
+ node->Component.Class = ControllerClass;
+ node->Component.Type = DiskController;
+ switch (sub_class) {
+ case 0: node->Component.Class = AdapterClass;
+ node->Component.Type = ScsiAdapter;
+ node->ComponentName = "scsi";
+ (void) add_new_child(node, "disk",
+ ControllerClass, DiskController);
+ (void) add_new_child(node, "tape",
+ ControllerClass, TapeController);
+ break;
+ case 1: node->ComponentName = "multi"; // IDE, actually
+ break;
+ case 2: node->ComponentName = "floppy";
+ break;
+ case 3: node->ComponentName = "ipi";
+ break;
+ default: node->ComponentName = "other";
+ break;
+ }
+ goto ok;
+
+ case 2:
+ node->Component.Class = ControllerClass;
+ node->Component.Type = NetworkController;
+ goto ok;
+
+ case 3:
+ node->Component.Class = ControllerClass;
+
+#ifdef rev1_30
+ node->Component.Type = DisplayController;
+#else
+ if (sub_class == 0 && prog_class == 0) {
+ node->Component.Type = DisplayController;
+ update_display_node(node);
+ } else {
+ node->Component.Type = OtherController;
+ }
+
+#endif
+ goto ok;
+
+ case 4:
+ node->Component.Class = ControllerClass;
+ switch (sub_class) {
+ case 0: node->Component.Type = DisplayController;
+ goto ok;
+ case 1: node->Component.Type = AudioController;
+ goto ok;
+ }
+ break;
+
+ case 5:
+ //
+ // What are we to do about memory cards?
+ //
+ break;
+
+ case 6:
+ node->Component.Class = AdapterClass;
+ if (sub_class == 2) {
+ node->Component.Type = EisaAdapter;
+ node->ComponentName = "eisa";
+ } else {
+ node->Component.Type = MultiFunctionAdapter;
+ node->ComponentName = "multi";
+ }
+ goto ok;
+
+ }
+
+ //
+ // What is this thing?
+ //
+ node->Component.Class = ControllerClass;
+ node->Component.Type = OtherController;
+ node->ComponentName = "other";
+ok:
+ if( VrDebug & VRDBG_TREE ) {
+ DisplayConfig(&node->Component);
+ }
+ return (1);
+}
+
+/*
+ * ScsiAdapter nodes have some special rules. The child controllers' Key
+ * values are the SCSI target ID, not the instance, and the child
+ * controllers' Identifiers are specified to be the concatenation of
+ * the vendor and product name fields as returned from INQUIRY.
+ *
+ * Worse news: SCSI devices may be wildcarded, so we've got to probe
+ * the whole bus here if we find a wildcard node.
+ *
+ * As an optimization, record the fact that we've probed the bus
+ * so we need probe only once. This eliminates duplicate probes as
+ * the firmware customarily reports both a disk and tape wildcard.
+ * The list of probed nodes is an array of "sufficient" size.
+ * Yes, I know.
+ */
+
+STATIC CONFIGURATION_NODE *
+convert_SCSI_device(PCONFIGURATION_NODE node)
+{
+ PCONFIGURATION_NODE newnode, parent=node->Parent;
+ CONFIGURATION_TYPE type = node->Component.Type, newtype;
+ phandle ph = node->OfPhandle;
+ phandle parentph = parent->OfPhandle;
+ static PCONFIGURATION_NODE done_list[32] = { 0 };
+ reg *regp;
+ char *path;
+ int i;
+ ihandle ih;
+ UCHAR inq[] = { 0x12, 0, 0, 0, 0xff, 0 };
+ ULONG res[2];
+ UCHAR *inq_data;
+ static int lock = 0;
+ int max_scsi_target = 8, scsi_host_id = 7;
+ int tmp_scsi_host_id = -1;
+
+
+
+ if (lock++) {
+ --lock;
+ return(0);
+ }
+
+ debug(VRDBG_ENTRY|VRDBG_TREE|VRDBG_SCSI,
+ "convert_SCSI_device: node 0x%x Begin.....\n", node);
+
+ if (OFGetproplen(ph, "reg") > 0) {
+ regp = get_reg_prop(ph, "reg", 0);
+ node->Component.Key = regp->hi;
+ node->Child->Component.Key = 0;
+ --lock;
+ return (node);
+ }
+
+ debug(VRDBG_SCSI|VRDBG_TREE,
+ "convert_SCSI_device: wildcard node (0x%x) parent (0x%x)\n",
+ node, parent);
+ VRDBG(VRDBG_SCSI, vr_dump_config_node(node));
+
+ //
+ // Discard the existing node: it's a wildcard and does
+ // us no good.
+ //
+ debug(VRDBG_SCSI, "convert_SCSI_device: parent child is(0x%x)\n",
+ parent->Child);
+ if (parent->Child == node) {
+ parent->Child = node->Peer;
+ debug(VRDBG_SCSI, "convert_SCSI_device: reset parent->Child \n");
+ VRDBG(VRDBG_SCSI, vr_dump_config_node(parent->Child));
+ }
+ for (newnode = parent->Child; newnode; newnode = newnode->Peer) {
+ debug(VRDBG_SCSI, "convert_SCSI_device: new node (0x%x)\n",newnode);
+ if (newnode->Peer == node) {
+ newnode->Peer = node->Peer;
+ node->Peer = 0;
+ }
+ }
+ if (node->Child) {
+ free((char *) node->Child);
+ }
+
+ //
+ // and finally, free the node...
+ //
+ free((char *) node);
+
+
+ //
+ // Have we already done this SCSI bus?
+ //
+ for (i = 0; i < 32; ++i) {
+ if (done_list[i] == 0) {
+ break;
+ }
+ if (done_list[i] == parent) {
+ debug(VRDBG_SCSI|VRDBG_TREE,
+ "already did node (0x%x)\n", parent);
+ --lock;
+ return (0);
+ }
+ }
+ if (i >= 32) {
+ fatal("Too many (>32) SCSI adapters!\n");
+ }
+ done_list[i] = parent;
+
+ if (get_bool_prop(parentph, "wide")) {
+ debug(VRDBG_TREE|VRDBG_SCSI, "SCSI controller is wide \n");
+
+ max_scsi_target = 16;
+
+ tmp_scsi_host_id = get_int_prop(parentph, "scsi-initiator-id");
+
+ debug(VRDBG_SCSI, "SCSI_Initiator_Id = %x\n", tmp_scsi_host_id);
+ if ( (tmp_scsi_host_id >= 0) && (tmp_scsi_host_id < 16) ) {
+ scsi_host_id = tmp_scsi_host_id;
+ }
+ }
+
+ //
+ // Build the parent adapter's path.
+ //
+ path = NodeToPath(parent);
+ ih = OFOpen(path);
+
+ //
+ // Loop through possible targets, and record each one
+ // which responds.
+ //
+ for (i = 0; i < max_scsi_target; ++i) {
+ if (i == scsi_host_id) {
+ continue; // don't want to probe the scsi host!
+ }
+
+ //
+ // This algorithm uses methods that are standard
+ // in the scsi node, but are not explicitly exported
+ // through the client interface--thus the "call-method."
+ //
+ OFCallMethod(0, 4, 0, "set-address", ih, i, 0);
+ OFCallMethod(2, 5, res, "short-data-command", ih, 6, inq, 0xff);
+ if (res[0] != 0) {
+ continue;
+ }
+
+ //
+ // The command succeeded.
+ //
+ inq_data = (UCHAR *) res[1];
+ if (inq_data[0] == 0x7f) {
+ continue;
+ }
+
+ //
+ // What kind of device are we looking for?
+ //
+ debug(VRDBG_TREE|VRDBG_SCSI,
+ "convert_SCSI_device: Device Found @ id %d\n",i);
+ newtype = ScsiNodeType[inq_data[0]];
+ debug(VRDBG_TREE|VRDBG_SCSI,
+ "convert_SCSI_device:\t\t '%s' of Type '%s'\n",
+ ScsiNodeName[inq_data[0]], TypeNames[newtype]);
+ //
+ // This target is for real. Add a new node to represent
+ // this device. Touch up the node as necessary
+ // for proper key, identifier, etc.
+ //
+ newnode = add_new_child(parent, ScsiNodeName[inq_data[0]],
+ ControllerClass, newtype);
+
+ newnode->OfPhandle = ph;
+ newnode->Component.Key = i;
+ newnode->Component.Identifier = (char *)zalloc(29);
+ bcopy(&inq_data[8], newnode->Component.Identifier, 28);
+ newnode->Component.IdentifierLength = 29;
+ newnode->Wildcard = 1;
+ newnode->WildcardAddrPath = (char *) zalloc(6);
+ strcpy(newnode->WildcardAddrPath, "@X,0");
+
+ //
+ // Convert scsi id to hex string value...
+ //
+ if (i < 10) {
+ newnode->WildcardAddrPath[1] = '0' + i;
+ } else {
+ newnode->WildcardAddrPath[1] = 'a' + (i-10);
+ }
+
+ if (!convert_controller(newnode)) {
+ debug(VRDBG_TEST|VRDBG_SCSI|VRDBG_TREE,
+ "Convert_SCSI_device: failed convert_controller\n");
+ }
+ newnode->Child->Component.Key = 0;
+ newnode->Child->Wildcard = 1;
+
+ } // end of for loop probing scsi bus
+ OFClose(ih);
+ free(path);
+ --lock;
+ return (0); // Zero because this was a wildcard node; don't convert.
+}
+
+/*
+ * Like SCSI, devices may be wildcarded, so we've got to probe
+ * the whole bus here if we find a wildcard node.
+ */
+STATIC CONFIGURATION_NODE *
+convert_IDE_device(PCONFIGURATION_NODE node)
+{
+ PCONFIGURATION_NODE newnode, parent=node->Parent;
+ CONFIGURATION_TYPE type = node->Component.Type, newtype;
+ phandle ph = node->OfPhandle;
+ static PCONFIGURATION_NODE done_list[32] = { 0 };
+ reg *regp;
+ char *path;
+ int i;
+ ihandle ih;
+ ULONG res[3];
+ static int lock = 0;
+
+ if (lock++) {
+ --lock;
+ return(0);
+ }
+ debug(VRDBG_TREE, "convert_IDE_device: node 0x%x\n", node);
+
+ if (OFGetproplen(ph, "reg") > 0) {
+ regp = get_reg_prop(ph, "reg", 0);
+ node->Component.Key = regp->hi;
+ node->Child->Component.Key = 0;
+ --lock;
+ return (node);
+ }
+
+ debug(VRDBG_IDE, "convert_IDE_device: wildcard node (0x%x)\n", node);
+ VRDBG(VRDBG_IDE, vr_dump_config_node(node));
+
+ //
+ // Discard the existing node: it's a wildcard and does
+ // us no good.
+ //
+
+ debug(VRDBG_IDE, "convert_IDE_device: parent child is(0x%x)\n",
+ parent->Child);
+ if (parent->Child == node) {
+ //
+ // remove this node from the parent's lineage...
+ //
+ parent->Child = node->Peer;
+ debug(VRDBG_IDE, "convert_IDE_device: reset parent->Child \n");
+ VRDBG(VRDBG_IDE, vr_dump_config_node(parent->Child));
+ }
+
+ //
+ // Run the list of peers and see who points to this wild card node.
+ // Once the wildcard's sibling is located, remove the wildcard
+ // from the "peer" list.
+ //
+ for (newnode = parent->Child; newnode; newnode = newnode->Peer) {
+ debug(VRDBG_IDE, "convert_IDE_device: new node (0x%x)\n",newnode);
+ if (newnode->Peer == node) {
+ //
+ // Now, remove this node from its peer(s)'s line
+ // of siblings....
+ //
+ newnode->Peer = node->Peer;
+ debug(VRDBG_IDE, "convert_IDE_device: reset newnode->Peer \n");
+ VRDBG(VRDBG_IDE, vr_dump_config_node(newnode));
+ node->Peer = 0;
+ }
+ }
+
+ //
+ // make sure this node's children are freed up since
+ // the children of a wild card node are wild themselves.
+ //
+ if (node->Child) {
+ debug(VRDBG_IDE, "convert_IDE_device: free child(0x%x)\n",
+ node->Child);
+ free((char *) node->Child);
+ }
+
+ //
+ // and finally, zero and free the node...
+ //
+ free((char *) node);
+
+ //
+ // Have we already done this IDE bus?
+ //
+ for (i = 0; i < 32; ++i) {
+ if (done_list[i] == 0) {
+ break;
+ }
+ if (done_list[i] == parent) {
+ debug(VRDBG_IDE|VRDBG_TREE,
+ "already did node (0x%x)\n", parent);
+ --lock;
+ return (0);
+ }
+ }
+
+ if (i >= 32){
+ fatal("Too many (>32) IDE adapters!\n");
+ }
+ done_list[i] = parent;
+
+ //
+ // Build the parent adapter's path.
+ //
+ path = NodeToPath(parent);
+ ih = OFOpen(path);
+ //
+ // Loop through possible targets, and record each one
+ // which responds.
+ //
+
+ for (i = 0; i < MAX_IDE_DEVICE; ++i) {
+ //
+ // This algorithm uses methods that are standard
+ // in the ide package, but are not explicitly exported
+ // through the client interface--thus the "call-method."
+ //
+
+ OFCallMethod(3, 3, res, "ide-drive-inquiry", ih, i);
+ //
+ // The command succeeded.
+ //
+
+ if (res[0] == 0) {
+ continue;
+ }
+
+ debug(VRDBG_TREE, "convert_IDE_device: Device Found @ id %d\n",i);
+ newtype = ScsiNodeType[res[1]];
+ debug(VRDBG_TREE, "convert_IDE_device:\t\t '%s' of Type '%s'\n",
+ ScsiNodeName[res[1]], TypeNames[newtype]);
+
+ //
+ // What kind of device are we looking for?
+ //
+ newnode = add_new_child(parent, ScsiNodeName[res[1]],
+ ControllerClass, newtype);
+ newnode->OfPhandle = ph;
+ newnode->Component.Key = i;
+ newnode->Component.Identifier = "disk";
+ newnode->Component.IdentifierLength = 5;
+ newnode->Wildcard = 1;
+ newnode->WildcardAddrPath = (char *) zalloc(6);
+ strcpy(newnode->WildcardAddrPath, "@X,0");
+ newnode->WildcardAddrPath[1] = '0' + i;
+
+ if (!convert_controller(newnode)) {
+ debug(VRDBG_TEST,
+ "Convert_IDE_device: failed convert_controller\n");
+ }
+ newnode->Child->Component.Key = 0;
+ newnode->Child->Wildcard = 1;
+
+ }
+ OFClose(ih);
+ free(path);
+ --lock;
+ return (0); // Zero because this was a wildcard node; don't convert.
+}
+
+#define prl_t CM_PARTIAL_RESOURCE_LIST
+#define prd_t CM_PARTIAL_RESOURCE_DESCRIPTOR
+
+STATIC prl_t *
+grow_prl(PCONFIGURATION_NODE node, int dev_specific)
+{
+ prl_t *prl;
+ int datalen;
+
+ if (node->ConfigurationData == (prl_t *) 0) {
+ node->ConfigurationData =
+ (PCM_PARTIAL_RESOURCE_LIST)
+ zalloc(sizeof(CM_PARTIAL_RESOURCE_LIST) + dev_specific);
+ prl = node->ConfigurationData;
+ prl->Version = 1;
+ prl->Revision = 2;
+ prl->Count = 0;
+ node->Component.ConfigurationDataLength =
+ sizeof(CM_PARTIAL_RESOURCE_LIST) + dev_specific;
+ return (prl);
+ }
+ datalen = node->Component.ConfigurationDataLength +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + dev_specific;
+ node->Component.ConfigurationDataLength = datalen;
+ prl = (prl_t *) zalloc(datalen);
+ datalen -= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + dev_specific;
+ bcopy((char *) node->ConfigurationData, (char *) prl, datalen);
+ free((char *)node->ConfigurationData);
+ node->ConfigurationData = prl;
+ return(prl);
+}
+
+/*
+ * This extremely ad hoc routine is called when converting a floppy
+ * controller, and builds the appropriate device-specific data struct
+ * in the floppy peripheral (which is a child of the controller node).
+ */
+STATIC VOID
+convert_config_floppy(CONFIGURATION_NODE *node)
+{
+ PCM_FLOPPY_DEVICE_DATA fdd;
+ prl_t *prl;
+ prd_t *prd;
+
+ debug(VRDBG_TREE, "Convert_config_floppy: node 0x%x\n", *node);
+ node->ComponentName = "disk";
+ node->Component.Identifier = "I82077";
+ node->Component.IdentifierLength = 7;
+
+ node = node->Child;
+ //
+ // Add space for the floppy configuration data to the end of the
+ // configuration node:
+ //
+ prl = grow_prl(node, sizeof(CM_FLOPPY_DEVICE_DATA));
+
+ //
+ // set the partial resource descriptor pointer to the end of the
+ // configuration node before this new data area was added:
+ //
+ prd = &prl->PartialDescriptors[prl->Count];
+
+ //
+ // Tell the registry this data is device specific, and the resource
+ // is device exclusive. Basically, fill out a partial resource
+ // descriptor for the floppy:
+ //
+ prd->Type = CmResourceTypeDeviceSpecific;
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;
+ prd->Flags = 0;
+ prd->u.DeviceSpecificData.DataSize = sizeof(CM_FLOPPY_DEVICE_DATA);
+
+ //
+ // finally, increment the count to match the increase in the data
+ // added to the partial resource list
+ //
+ prl->Count += 1;
+
+ //
+ // Device-specific data begins immediately after
+ // its descriptor.
+ //
+ fdd = (PCM_FLOPPY_DEVICE_DATA)
+ ((char *) prd + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+ //
+ // These need to be version 1.2, else all the extended fields
+ // like "HeadSettleTime" are assumed to be valid and must be
+ // filled in, presumably by a scientist.
+ //
+ fdd->Version = 1;
+ fdd->Revision = 2;
+ strcpy(fdd->Size, "3.5");
+ fdd->MaxDensity = 1440;
+ /* All else is zero. */
+}
+
+/*
+ * This extremely ad hoc routine is called when converting a serial
+ * controller, and builds the appropriate device-specific data struct.
+ */
+STATIC VOID
+convert_config_serial(CONFIGURATION_NODE *node)
+{
+ PCM_SERIAL_DEVICE_DATA serd;
+ prl_t *prl;
+ prd_t *prd;
+
+ debug(VRDBG_TREE, "Convert_config_serial: node 0x%x\n", *node);
+ prl = grow_prl(node, sizeof(CM_SERIAL_DEVICE_DATA));
+ prd = &prl->PartialDescriptors[prl->Count];
+ prd->Type = CmResourceTypeDeviceSpecific;
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;
+ prd->Flags = 0;
+ prd->u.DeviceSpecificData.DataSize = sizeof(CM_SERIAL_DEVICE_DATA);
+ prl->Count += 1;
+
+ //
+ // Device-specific data begins immediately after
+ // its descriptor.
+ //
+ serd = (PCM_SERIAL_DEVICE_DATA)
+ ((char *) prd + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+ serd->Version = 1;
+ serd->Revision = 2;
+ if (VrDebug & SANDALFOOT) {
+ serd->BaudClock = 0x409980;
+ } else {
+ serd->BaudClock = 1843200;
+ }
+}
+
+/*
+ * This extremely ad hoc routine is called when converting the system
+ * node, and builds the appropriate device-specific data struct.
+ */
+STATIC VOID
+convert_system_node(CONFIGURATION_NODE *node)
+{
+ prl_t *prl;
+ prd_t *prd;
+ phandle ph;
+ PCHAR pData;
+ PCHAR pFirmwareVersion, pVeneerVersion;
+ PCHAR pVeneerVersionId = "Veneer";
+ PCHAR pFirmwareVersionId = "Firmware";
+#ifdef BUILTBY
+ PCHAR pBuiltById = "Built By";
+ PCHAR pBuiltBy;
+#endif
+ CHAR **srcPairs[] = {
+ &pFirmwareVersionId,
+ &pFirmwareVersion,
+ &pVeneerVersionId,
+ &pVeneerVersion,
+#ifdef BUILTBY
+ &pBuiltById,
+ &pBuiltBy,
+#endif
+ NULL
+ };
+ LONG dataSize;
+ LONG n;
+
+ debug(VRDBG_TREE, "Convert_system_node: node 0x%x\n", *node);
+
+ //
+ // The configuration data being built here will consist of
+ // multiple null terminated strings terminated by an empty
+ // string (ie. '\0'). The strings will consist of pairs
+ // of strings with the first string being the description
+ // of the second (paired) string.
+ //
+ // Example:
+ //
+ // "VeneerVersion" "FirmWorks,ENG,00.23,1995-04-27,14:42:21,GENERAL"
+ //
+
+ //
+ // grab the firmware and veneer versions
+ //
+
+ pVeneerVersion = VeneerVersion();
+ ph = OFFinddevice("/openprom");
+ pFirmwareVersion = get_str_prop(ph, "model", NOALLOC);
+ level_equals_vector = (OFGetproplen(ph,"arc-interrupt-level=vector") >= 0);
+ if (OFGetproplen(ph,"arc-interrupt-level") > 0) {
+ default_interrupt_level = get_int_prop(ph, "arc-interrupt-level");
+ }
+ if (OFGetproplen(ph,"arc-interrupt-affinity") > 0) {
+ default_interrupt_affinity = get_int_prop(ph, "arc-interrupt-affinity");
+ }
+
+#ifdef BUILTBY
+ //
+ // add the built by if defined
+ //
+ pBuiltBy = IQUOTE(BUILTBY);
+#endif
+
+ //
+ // the length of all strings + null terminaters + empty string
+ //
+
+ dataSize = 0;
+ for (n = 0; srcPairs[n]; n++) {
+ dataSize += strlen(*srcPairs[n]) + 1;
+ }
+ dataSize += 2*sizeof(CHAR); // an empty string (2* just for good measure)
+
+ prl = grow_prl(node, dataSize);
+ prd = &prl->PartialDescriptors[prl->Count];
+ prd->Type = CmResourceTypeDeviceSpecific;
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;
+ prd->Flags = 0;
+ prd->u.DeviceSpecificData.DataSize = dataSize;
+ prl->Count += 1;
+ debug(VRDBG_TEST, "Count is now...%x\n", prl->Count);
+
+ //
+ // Device-specific data begins immediately after
+ // its descriptor.
+ //
+
+ pData = (char *) prd + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+ {
+ //
+ // Now stuff the strings into the data buffer.
+ //
+
+ PCHAR dst = pData;
+ PCHAR src;
+
+ for (n = 0; srcPairs[n]; n++) {
+ src = *srcPairs[n];
+ strcpy(dst, src);
+ dst += strlen(src)+1;
+ }
+
+ *dst = '\0';
+ }
+
+ return;
+
+}
+
+//
+// 8042 subtrees compliant with the HRP binding define a new address
+// space for their children. Reg[0] in the child specifies the keyboard (0)
+// or aux (1) port of the 8042. All 8042 child nodes--keyboard and
+// mouse--are translated to ARC nodes--kbd and point--that have the same
+// PORT information in the registry. The reg information in the device
+// tree is suppressed, and the NT driver (i8042prt) sorts out who gets
+// what port on the 8042.
+// Although we shouldn't, we'll just "know" that an 8042 has two reg
+//
+STATIC VOID
+convert_config_i8042(CONFIGURATION_NODE *node)
+{
+ phandle parent;
+ prl_t *prl;
+ prd_t *prd;
+ int i;
+ reg *regp;
+
+ debug(VRDBG_TREE, "Convert_config_i8042: node 0x%x\n", *node);
+ parent = OFParent(node->OfPhandle);
+ for (i = 0; i < 2; ++i) {
+ regp = get_reg_prop(parent, "reg", i);
+ prl = grow_prl(node, 0);
+ prd = &prl->PartialDescriptors[prl->Count];
+ prd->Type = CmResourceTypePort;
+ prd->Flags = CM_RESOURCE_PORT_IO;
+ prd->u.Port.Start.LowPart = regp->lo;
+ prd->u.Port.Start.HighPart = 0;
+ prd->u.Port.Length = regp->size;
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;
+ prl->Count += 1;
+ }
+}
+
+STATIC VOID
+replace_isa_name(CONFIGURATION_NODE *node, int port)
+{
+ struct pnp_info *pnp;
+
+ for (pnp = pnp_data; pnp->port != 0; ++pnp) {
+ if (pnp->port == (unsigned int) port) {
+ node->Component.Identifier = pnp->id;
+ node->Component.IdentifierLength = strlen(pnp->id) + 1;
+ break;
+ }
+ }
+}
+
+STATIC VOID
+convert_config(CONFIGURATION_NODE *node)
+{
+ phandle ph = node->OfPhandle;
+ prl_t *prl;
+ prd_t *prd=0;
+ reg *regp;
+ int prop;
+
+ debug(VRDBG_TREE, "convert_config: node 0x%x, name %s identifier %s\n",
+ node, node->ComponentName, node->Component.Identifier);
+ //
+ // The "arc-config-data" property totally overrides the conversion
+ // process, providing a complete verbatim ARC configuration data
+ // structure.
+ //
+ if ((prop = OFGetproplen(ph, "arc-config-data")) >= 0) {
+ char *buf;
+ debug(VRDBG_ARCDATA, "convert_config: arc data override: 0x%x\n", node);
+ buf = zalloc(prop);
+ (VOID) OFGetprop(ph, "arc-config-data", buf, prop);
+ node->ConfigurationData = (PCM_PARTIAL_RESOURCE_LIST) buf;
+ node->Component.ConfigurationDataLength = prop;
+
+ if (((prop = OFGetproplen(ph, "reg")) > 0)
+ && (strcmp(node->Parent->Component.Identifier, "ISA") == 0)) {
+ regp = get_reg_prop(ph, "reg", 0);
+ replace_isa_name(node, regp->lo);
+ }
+ return;
+ }
+
+ if ((prop = OFGetproplen(ph, "reg")) > 0) {
+ if (strcmp(node->ComponentName, "memory") == 0) {
+ regp = get_reg_prop(ph, "reg", 0);
+ ADD_MEM_RESOURCE(regp, node);
+ } else {
+ if (strcmp(node->Parent->Component.Identifier, "PCI") == 0) {
+ regp = get_reg_prop(ph, "reg", 1);
+ configure_pci_node(regp, node);
+ } else {
+ if (strcmp(node->Component.Identifier, "I8042PRT") == 0) {
+ convert_config_i8042(node);
+ } else {
+ regp = get_reg_prop(ph, "reg", 0);
+ ADD_IO_RESOURCE(regp, node);
+ replace_isa_name(node, prd->u.Port.Start.LowPart);
+ }
+ }
+ }
+ }
+
+ if ((prop = OFGetproplen(ph, "interrupts")) > 0) {
+ int level;
+ level = get_int_prop(ph, "interrupts");
+ ADD_INT_RESOURCE(level, node);
+ //
+ // Now check for deviations from the "NORM" in the form of
+ // arc-... properties that this particular system uses to
+ // override standard tree values.
+ //
+ if ((prop = OFGetproplen(ph, "arc-interrupt-flags")) > 0) {
+ prop = get_int_prop(ph, "arc-interrupt-flags");
+ prd->Flags = prop;
+ }
+ if ((prop = OFGetproplen(ph, "arc-interrupt-level")) > 0) {
+ prop = get_int_prop(ph, "arc-interrupt-level");
+ prd->u.Interrupt.Level = prop;
+ }
+
+ if ((prop = OFGetproplen(ph, "arc-interrupt-vector")) > 0) {
+ prop = get_int_prop(ph, "arc-interrupt-vector");
+ prd->u.Interrupt.Vector = prop;
+ }
+
+ if ((prop = OFGetproplen(ph, "arc-interrupt-affinity")) > 0) {
+ (int)(prd->u.Interrupt.Affinity) =
+ get_int_prop(ph, "arc-interrupt-affinity");
+ }
+
+ }
+
+ if ((prop = OFGetproplen(ph, "dma")) > 0) {
+ prop = get_int_prop(ph, "dma");
+ ADD_DMA_RESOURCE(prop, node);
+ if (prop != sizeof(int)) {
+ //
+ // Multiple cells are used to encode PNP data for
+ // AIX--just pick off the first cell.
+ //
+ char buf[sizeof(int)];
+ OFGetprop(ph, "dma", buf, sizeof(int));
+ prop = decode_int(buf);
+ prd->u.Dma.Channel = prop;
+ }
+ }
+
+ if ((prop = OFGetproplen(ph, "arc-device-specific")) > 0) {
+ ADD_DEVICE_SPECIFIC_RESOURCE(prop, node);
+ }
+
+ //
+ // Now check for special-case conversions.
+ //
+
+ debug(VRDBG_TREE, "\tCheck special case, Name '%s'\n",
+ node->ComponentName);
+
+ if (strcmp(node->ComponentName, "floppy") == 0) {
+ convert_config_floppy(node);
+ }
+
+ if (strcmp(node->ComponentName, "serial") == 0) {
+ convert_config_serial(node);
+ }
+
+#ifdef SANDALFOOT_YET_LIVES
+ //
+ // Empirically, Sandalfoot systems have this stuff (register
+ // init constants?) in their ARC trees. Ergo, we put it
+ // in our ARC trees too. Note that this stuff doesn't look
+ // like a normal node.
+ //
+ if (strcmp(node->ComponentName, "video") == 0) {
+ PULONG up;
+
+ node = node->Child;
+ prl = grow_prl(node, 0x1a);
+ prl->Version = 1;
+ prl->Revision = 0;
+
+ up = (PULONG) &prl->Count;
+ *up++ = 0x3e800400;
+ *up++ = 0x03e807d0;
+ *up++ = 0x030005dc;
+ *up++ = 0x00010027;
+ *up++ = 0x01570001;
+ *up++ = 0x00000112;
+
+ }
+#endif
+
+ if (node->Component.Type == ArcSystem) {
+ convert_system_node(node);
+ }
+}
+
+STATIC VOID
+convert_cache(CONFIGURATION_NODE *node)
+{
+ phandle ph = node->OfPhandle;
+ CONFIGURATION_NODE *newnode;
+ int block_size, cache_size;
+
+ debug(VRDBG_TREE, "Convert_cache: node 0x%x\n", node);
+ if (get_bool_prop(ph, "cache-unified")) {
+ cache_size = get_int_prop(ph, "i-cache-size");
+ if (cache_size == -1) {
+ fatal("Couldn't find 'i-cache-size': %s\n", node->ComponentName);
+ }
+ block_size = get_int_prop(ph, "i-cache-block-size");
+ if (block_size == -1) {
+ block_size = 8;
+ }
+
+ node->Component.Key = 0x01000000;
+ node->Component.Key |= log2(block_size) << 16;
+ node->Component.Key |= log2(cache_size >> PAGE_SHIFT);
+
+ return;
+ }
+
+ //
+ // Are we an I-cache?
+ //
+ if (get_int_prop(ph, "i-cache-size") != -1) {
+ cache_size = get_int_prop(ph, "i-cache-size");
+ block_size = get_int_prop(ph, "i-cache-block-size");
+ if (block_size == -1) {
+ fatal("Couldn't find 'i-cache-block-size': %s\n",
+ node->ComponentName);
+ }
+
+ node->Component.Key = 0x01000000;
+ node->Component.Key |= log2(block_size) << 16;
+ node->Component.Key |= log2(cache_size >> PAGE_SHIFT);
+
+ if (node->Parent->Component.Type == CentralProcessor) {
+ node->Component.Type = PrimaryIcache;
+ } else {
+ node->Component.Type = SecondaryIcache;
+ }
+
+ if (get_int_prop(ph, "d-cache-size") == -1) {
+ return;
+ }
+
+ //
+ // Uh-oh, there's a split cache here.
+ //
+ newnode = new(CONFIGURATION_NODE);
+ bcopy((char *) node, (char *) newnode, sizeof(CONFIGURATION_NODE));
+ newnode->Child = 0;
+ node->Peer = newnode;
+ node = newnode;
+ }
+
+ //
+ // Are we a D-cache?
+ //
+ if (get_int_prop(ph, "d-cache-size") != -1) {
+ cache_size = get_int_prop(ph, "d-cache-size");
+ block_size = get_int_prop(ph, "d-cache-block-size");
+ if (block_size == -1) {
+ fatal("Couldn't find 'd-cache-block-size': %s\n",
+ node->ComponentName);
+ }
+
+ node->Component.Key = 0x01000000;
+ node->Component.Key |= log2(block_size) << 16;
+ node->Component.Key |= log2(cache_size >> PAGE_SHIFT);
+
+ if (node->Parent->Component.Type == CentralProcessor) {
+ node->Component.Type = PrimaryDcache;
+ } else {
+ node->Component.Type = SecondaryDcache;
+ }
+ }
+}
+
+STATIC VOID
+update_display_node(PCONFIGURATION_NODE node)
+{
+ PCONFIGURATION_NODE n;
+
+ if (DisplayNode == 0) {
+ DisplayNode = node;
+ return;
+ }
+
+ if (DisplayNode->Child) {
+ free((char *) DisplayNode->Child);
+ }
+
+ n = DisplayNode->Parent;
+ if (n->Child == DisplayNode) {
+ n->Child = DisplayNode->Peer;
+ } else {
+ for (n = n->Child; n && n->Peer != DisplayNode; n = n->Peer) {
+ ;
+ }
+ if (n) {
+ n->Peer = DisplayNode->Peer;
+ }
+ }
+
+ free((char *) DisplayNode);
+ DisplayNode = node;
+}
+
+STATIC VOID
+configure_pci_node(reg *regp, PCONFIGURATION_NODE node)
+{
+ prl_t *prl;
+ prd_t *prd;
+ debug(VRDBG_TREE, "Convert_pci_node: node 0x%x\n", node);
+ if (regp != NULL) {
+ prl = grow_prl(node, 0);
+ prd = &prl->PartialDescriptors[prl->Count];
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ switch (regp->hi & 0x0f000000) {
+ case 0x01000000:
+ prd->Type = CmResourceTypePort;
+ prd->Flags = CM_RESOURCE_PORT_IO;
+ prd->u.Port.Start.LowPart = regp->lo;
+ prd->u.Port.Start.HighPart = 0;
+ break;
+ case 0x02000000:
+ case 0x03000000:
+ //
+ // XXX this is really quite bogus - we should probably
+ // look in the assigned-addresses property to find
+ // the actual assigned base address. However, we
+ // don't really know yet exactly what this property is
+ // supposed to contain for PCI devices.
+ //
+
+ prd->Type = CmResourceTypeMemory;
+ prd->Flags = 0;
+ prd->u.Memory.Start.LowPart = regp->lo;
+ prd->u.Memory.Start.HighPart = 0;
+ // XXX do something for 64-bit memory space
+ break;
+ }
+ prd->u.Port.Length = regp->size;
+ prl->Count += 1;
+ }
+
+}
+
+/*
+ * Routine: vr_dump_config_node(PCONFIGURATION_NODE)
+ *
+ * Description:
+ * To dump the open firmware info for the given node.
+ */
+
+VOID
+vr_dump_config_node(PCONFIGURATION_NODE node)
+{
+ CONFIGURATION_CLASS class;
+ CONFIGURATION_TYPE type;
+ PCHAR name="XXX";
+
+ if (!node) {
+ warn("vr_dump_config_node: NODE is invalid: 0x%x\n",node);
+ return;
+ }
+ class = node->Component.Class;
+ type = node->Component.Type;
+
+ if (class > MaximumClass ) {
+ warn("vr_dump_config: class value maxed out: previously 0x%x\n",class);
+ class = MaximumClass;
+ }
+
+ if (type > MaximumType) {
+ warn("vr_dump_config: type value maxed out: previously 0x%x\n",type);
+ type = MaximumType;
+ }
+
+ //
+ // Dump information to identify this node.
+ //
+ warn("\ndump_node:\tName\t%s\n", node->ComponentName);
+ warn("\t\tClass\t%s\t\t\tParent 0x%x\n",
+ ClassNames[class], node->Parent);
+ warn("\t\tType\t%s\t\t\t /\n", TypeNames[type]);
+ warn("\t\tKey\t%d\t\t\t Current 0x%x ----> Peer 0x%x\n",
+ node->Component.Key, node, node->Peer);
+ warn("\t\t\t\t\t\t/\n");
+ warn("\t\t\t\t\tChild 0x%x\n\n",node->Child);
+
+}
diff --git a/private/ntos/boot/veneer/vrtree.h b/private/ntos/boot/veneer/vrtree.h
new file mode 100644
index 000000000..42015fa9d
--- /dev/null
+++ b/private/ntos/boot/veneer/vrtree.h
@@ -0,0 +1,153 @@
+
+/*
+ *
+ * Copyright (c) 1995,1996 FirePower Systems, Inc.
+ * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
+ *
+ * $RCSfile: vrtree.h $
+ * $Revision: 1.3 $
+ * $Date: 1996/06/15 23:21:16 $
+ * $Locker: $
+ *
+ */
+
+#ifndef VRTREE_H
+#define VRTREE_H
+
+#define ADD_MEM_RESOURCE(regp, node) { \
+ prl = grow_prl(node, 0); \
+ prd = &prl->PartialDescriptors[prl->Count]; \
+ prd->Type = CmResourceTypeMemory; \
+ prd->u.Memory.Start.LowPart = regp->lo; \
+ prd->u.Memory.Start.HighPart = 0; \
+ prd->u.Port.Length = regp->size; \
+ prd->Flags = 0; \
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;\
+ prl->Count += 1; \
+ }
+
+#define ADD_IO_RESOURCE(regp, node) { \
+ prl = grow_prl(node, 0); \
+ prd = &prl->PartialDescriptors[prl->Count];\
+ prd->ShareDisposition = CmResourceShareDeviceExclusive; \
+ \
+ prd->Type = CmResourceTypePort; \
+ prd->Flags = CM_RESOURCE_PORT_IO; \
+ prd->u.Port.Start.LowPart = regp->lo; \
+ prd->u.Port.Start.HighPart = 0; \
+ prd->u.Port.Length = regp->size; \
+ prl->Count += 1; \
+ }
+
+
+#define ADD_INT_RESOURCE(level, node) { \
+ prl = grow_prl(node, 0); \
+ prd = &prl->PartialDescriptors[prl->Count]; \
+ prd->u.Interrupt.Level = level; \
+ prd->Type = CmResourceTypeInterrupt; \
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;\
+ prd->Flags = CM_RESOURCE_INTERRUPT_LATCHED; \
+ prd->u.Interrupt.Vector = \
+ level_equals_vector ? \
+ level : default_interrupt_level; \
+ (int)(prd->u.Interrupt.Affinity) = default_interrupt_affinity;\
+ prl->Count += 1; \
+ }
+
+#define ADD_DMA_RESOURCE(prop, node) { \
+ prl = grow_prl(node, 0); \
+ prd = &prl->PartialDescriptors[prl->Count]; \
+ prd->Type = CmResourceTypeDma; \
+ prd->ShareDisposition = CmResourceShareDeviceExclusive; \
+ prd->u.Dma.Channel = prop; \
+ prl->Count += 1; \
+ }
+
+#define ADD_DEVICE_SPECIFIC_RESOURCE(prop, node) { \
+ char *buf;\
+ prl = grow_prl(node, prop);\
+ prd = &prl->PartialDescriptors[prl->Count];\
+ prd->Type = CmResourceTypeDeviceSpecific;\
+ prd->ShareDisposition = CmResourceShareDeviceExclusive;\
+ prd->Flags = 0;\
+ prd->u.DeviceSpecificData.DataSize = prop;\
+ prl->Count += 1;\
+ buf = ((char *) prd + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));\
+ (VOID) OFGetprop(ph, "arc-device-specific", buf, prop);\
+ }
+
+
+PCHAR TypeNames[]={
+ "ArcSystem",
+ "CentralProcessor",
+ "FloatingPointProcessor",
+ "PrimaryIcache",
+ "PrimaryDcache",
+ "SecondaryIcache",
+ "SecondaryDcache",
+ "SecondaryCache",
+ "EisaAdapter",
+ "TcAdapter",
+ "ScsiAdapter",
+ "DtiAdapter",
+ "MultiFunctionAdapter",
+ "DiskController",
+ "TapeController",
+ "CdromController",
+ "WormController",
+ "SerialController",
+ "NetworkController",
+ "DisplayController",
+ "ParallelController",
+ "PointerController",
+ "KeyboardController",
+ "AudioController",
+ "OtherController",
+ "DiskPeripheral",
+ "FloppyDiskPeripheral",
+ "TapePeripheral",
+ "ModemPeripheral",
+ "MonitorPeripheral",
+ "PrinterPeripheral",
+ "PointerPeripheral",
+ "KeyboardPeripheral",
+ "TerminalPeripheral",
+ "OtherPeripheral",
+ "LinePeripheral",
+ "NetworkPeripheral",
+ "SystemMemory",
+ "MaximumType"
+};
+
+PCHAR ClassNames[]={
+ "SystemClass",
+ "ProcessorClass",
+ "CacheClass",
+ "AdapterClass",
+ "ControllerClass",
+ "PeripheralClass",
+ "MemoryClass",
+ "MaximumClass",
+ "XX 8 XX",
+ "XX 9 XX"
+};
+
+PCHAR ScsiNodeName[] ={
+ "disk",
+ "tape",
+ "nada",
+ "nada",
+ "worm",
+ "cdrom"
+};
+
+
+CONFIGURATION_TYPE ScsiNodeType[] ={
+ DiskController,
+ TapeController,
+ MaximumType,
+ MaximumType,
+ WormController,
+ CdromController
+};
+#endif // VRTREE_H