root/sys/arch/vax/boot/xxboot/start.S
/*      $NetBSD: start.S,v 1.7 2020/04/06 01:43:26 snj Exp $ */
/*
 * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
 * All rights reserved.
 *
 * This code is derived from software contributed to Ludd by
 * Bertram Barth.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

 /* All bugs are subject to removal without further notice */
                

#define _LOCORE

#define __HAVE_OLD_DISKLABEL    /* not automatically added due to _LOCORE */
#define OMIT_DKTYPENUMS
#define OMIT_FSTYPENUMS
#include "sys/disklabel.h"

#include "../include/mtpr.h"
#include "../include/asm.h"             

_C_LABEL(_start):
_C_LABEL(start):
        .globl _C_LABEL(start)  # this is the symbolic name for the start
        .globl _C_LABEL(_start) # of code to be relocated. We can use this
                                # to get the actual/real address (pc-rel)
                                # or to get the relocated address (abs).

.org    0x00                    # uVAX booted from TK50 starts here
        brb     from_0x00       # continue behind dispatch-block

# At offset 0x02 we have a dual used area: VMB.EXE starts execution here,
# and uVAX-ROM looks for a pointer to a parameter block. We arrange for
# the parameter block offset to disassemble as a CASEL instructions which
# falls through to 0x08.
.org    0x02                    # information used by uVAX-ROM
        .byte   0xcf            # offset in words to identification area
        .byte   1               # this byte must be 1
        .word   0               # logical block number (word swapped) 
        .word   0               # of the secondary image

.org    0x08                    #
        brb     from_0x08       # skip ...

.org    0x0C                    # 11/750  & 8200 starts here
        movzbl  $1,_C_LABEL(from)# We booted from "old" rom.
        brw     cont_750


from_0x00:                      # uVAX from TK50 
        brw     start_uvax      # all uVAXen continue there

from_0x08:                      # Any machine from VMB
        movzbl  $4,_C_LABEL(from)               # Booted from full VMB
        /*
         * Read in block 1-15.
         */
        movl    52(%r11), %r7   # load iovec/bqo into %r7
        addl3   (%r7), %r7, %r6 # load qio into %r6
        pushl   %r11            # base of rpb
        pushl   $0              # virtual-flag 
        pushl   $33             # read-logical-block
        pushl   $1              # lbn to start reading
        pushl   $7680           # number of bytes to read
        pushab  start_uvax      # buffer-address 
        calls   $6, (%r6)       # call the qio-routine
        brw     start_uvax

# the complete area reserved for label
# must be empty (i.e. filled with zeroes).
# disklabel(8) checks that before installing
# the bootblocks over existing label.

.org    LABELOFFSET
        .globl  _C_LABEL(romlabel)
_C_LABEL(romlabel):
        .long   0

.org    LABELOFFSET + d_end_
# Make sure the parameter block is past the disklabel.
# If not, the next .org would try to move backwards.

/*
 * Parameter block for uVAX boot.
 */
#define VOLINFO         0       /* 1=single-sided  81=double-sided volumes */
#define SISIZE          16      /* size in blocks of secondary image */
#define SILOAD          0       /* load offset (usually 0) from the default */
#define SIOFF           0x200   /* byte offset into secondary image */

.org    0x19e   # do not move, see comment earlier about CASEL
        .byte   0x18            # must be 0x18 
        .byte   0x00            # must be 0x00 (MBZ) 
        .byte   0x00            # any value 
        .byte   0xFF - (0x18 + 0x00 + 0x00)     
                /* 4th byte holds 1s' complement of sum of previous 3 bytes */

        .byte   0x00            # must be 0x00 (MBZ) 
        .byte   VOLINFO
        .byte   0x00            # any value 
        .byte   0x00            # any value 

        .long   SISIZE          # size in blocks of secondary image 
        .long   SILOAD          # load offset (usually 0) 
        .long   SIOFF           # byte offset into secondary image 
        .long   (SISIZE + SILOAD + SIOFF)       # sum of previous 3 


        .align  2
        .globl  _C_LABEL(from)
_C_LABEL(from):
        .long   0

/*
 * After bootblock (LBN0) has been loaded into the first page 
 * of good memory by 11/750's ROM-code (transfer address
 * of bootblock-code is: base of good memory + 0x0C) registers
 * are initialized as:
 *      R0:     type of boot-device
 *                      0:      Massbus device
 *                      1:      RK06/RK07
 *                      2:      RL02
 *                      17:     UDA50
 *                      35:     TK50
 *                      64:     TU58
 *      R1:     (UBA) address of UNIBUS I/O-page
 *              (MBA) address of boot device's adapter
 *      R2:     (UBA) address of the boot device's CSR
 *              (MBA) controller number of boot device
 *      R6:     address of driver subroutine in ROM
 *
 * cont_750 reads in LBN1-15 for further execution.
 */
cont_750:
        movl    $_C_LABEL(start), %sp   # move stack to avoid clobbering the code
        pushr   $0x131          # save clobbered registers
        clrl    %r4             # %r4 == # of blocks transferred
        movab   _C_LABEL(start),%r5     # %r5 have base address for next transfer
        pushl   %r5             # ...on stack also (Why?)
1:      incl    %r4             # increment block count
        movl    %r4,%r8         # LBN is in %r8 for rom routine
        addl2   $0x200,%r5      # Increase address for next read
        cmpl    $16,%r4         # read 15 blocks?
        beql    2f              # Yep
        movl    %r5,(%sp)               # move address to stack also
        jsb     (%r6)           # read 512 bytes
        blbs    %r0,1b          # jump if read succeeded
        halt                    # otherwise die...
2:      tstl    (%sp)+          # remove boring arg from stack
        popr    $0x131          # restore clobbered registers
        brw     start_all       # Ok, continue...

/* uVAX main entry is at the start of the second disk block.  This is
 * needed for multi-arch CD booting where multiple architecture need
 * to shove stuff in boot block 0.
 */
        .org    0x200           # uVAX booted from disk starts here

start_uvax:
        movzbl  $2,_C_LABEL(from)       # Booted from subset-VMB
        brb     start_all

/*
 * start_all: stack already at RELOC, we save registers, move ourself
 * to RELOC and loads boot.
 */
start_all:
        movl    $_C_LABEL(start), %sp   # move stack to a better 
        pushr   $0x1fff                 # save all regs, used later.

        subl3   $_C_LABEL(start), $_C_LABEL(edata), %r0
                                        # get size of text+data (w/o bss)
        moval   _C_LABEL(start), %r1    # get actual base-address of code
        subl3   $_C_LABEL(start), $_C_LABEL(end), %r2
                                        # get complete size (incl. bss)
        movl    $_C_LABEL(start), %r3   # get relocated base-address of code
        movc5   %r0, (%r1), $0, %r2, (%r3)      # copy code to new location
        
        movpsl  -(%sp)
        movl    $relocated, -(%sp)      # return-address on top of stack 
        rei                             # can be replaced with new address
relocated:                              # now relocation is done !!!
        movl    %sp, _C_LABEL(bootregs)
        calls   $0, _C_LABEL(Xmain)     # call Xmain (gcc workaround)which is 
        halt                            # not intended to return ...

/*
 * hoppabort() is called when jumping to the newly loaded program.
 */
ENTRY(hoppabort, 0)
        movl    4(%ap),%r6
        movl    _C_LABEL(rpb),%r11
        mnegl   $1,%ap          # Hack to figure out boot device.
        movpsl  -(%sp)
        pushab  2(%r6)
        mnegl   $1,_C_LABEL(vax_load_failure)
        rei
#       calls   $0,(%r6)
        halt

ENTRY(unit_init, R6|R7|R8|R9|R10|R11)
        mfpr    $17,%r7                 # Wanted bu KDB
        movl    4(%ap),%r0              # init routine address
        movl    8(%ap),%r9              # RPB in %r9
        movl    12(%ap),%r1             # VMB argument list
        callg   (%r1),(%r0)
        ret

# A bunch of functions unwanted in boot blocks.
ENTRY(getchar, 0)
        halt

#ifndef USE_PRINTF
ENTRY(putchar, 0)
        ret

ENTRY(printf, 0)
        ret
#endif

ENTRY(panic, 0)
        halt