root/sys/arch/landisk/stand/bootxx/pbr.S
/*      $NetBSD: pbr.S,v 1.2 2012/01/21 19:44:30 nonaka Exp $   */

/*-
 * Copyright (C) 2005 NONAKA Kimihiro <nonaka@netbsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
 */

#include <machine/asm.h>
#include <sys/bootblock.h>

#ifdef BOOT_FROM_FAT
#define MBR_AFTERBPB    90              /* BPB size in FAT32 partition BR */
#else
#define MBR_AFTERBPB    62              /* BPB size in floppy master BR */
#endif

ENTRY(start)
        bra     start0
         .byte  0x11                    /* 0x4e11: cmp/pz r14... */
        .ascii  "NetBSD20"

        . = _C_LABEL(start) + MBR_BPB_OFFSET    /* move to start of BPB */

        . = _C_LABEL(start) + MBR_AFTERBPB      /* skip BPB */
start0:
        mova    mbr_end, r0
        mov.w   mbr_size, r2
        sub     r2, r0
        mov     r0, r11                 /* r11: own loaded address */

        mov.w   stack_offset, r1
        add     r1, r0
        mov     r0, r15                 /* r15: stack pointer */
        mov     r0, r10                 /* r10: load address */

        /* enable/flush cache */
        mov     #0, r4
        mov     #6, r0
        trapa   #0x3f

        /* Read from start of disk */
        mov     #0x40, r4               /* LBA */
        mov     #0, r5                  /* LBA #0 */
        mov     r10, r6                 /* buffer address */
        bsr     read_sectors_lba
         mov    #BOOTXX_SECTORS, r7     /* number of sectors */

        mov.l   @r11, r1
        mov.l   @r10, r2
        cmp/eq  r1, r2
        bt/s    pbr_read_ok
         mov    #0, r9                  /* r9: sector # */

        /* Search bootable partition */
        mov.w   part_offset, r12
        add     r10, r12                /* r12: pointer to partition entry */
        mov     #MBR_PART_COUNT, r8     /* r8: partition loop counter */
loop_part:
        mov.b   @(4, r12), r0
#ifdef BOOT_FROM_FAT
        cmp/eq  #MBR_PTYPE_FAT12, r0
        bt      found
        cmp/eq  #MBR_PTYPE_FAT16S, r0
        bt      found
        cmp/eq  #MBR_PTYPE_FAT16B, r0
        bt      found
        cmp/eq  #MBR_PTYPE_FAT32, r0
        bt      found
        cmp/eq  #MBR_PTYPE_FAT32L, r0
        bt      found
        cmp/eq  #MBR_PTYPE_FAT16L, r0
        bt      found
#else
        cmp/eq  #MBR_PTYPE_NETBSD, r0
#endif
        bf      next_part

found:
        /* found boot partition */
        mov.w   @(8, r12), r0
        mov     r0, r1
        mov.w   @(10, r12), r0
        extu.w  r1, r1
        shll16  r0
        or      r1, r0
        tst     r0, r0
        bt      next_part               /* start LBA == 0 ? */

        bra     boot_lba
         mov    r0, r9

next_part:
        dt      r8
        bf/s    loop_part
         add    #16, r12

ptn_error:
        /* Not found NetBSD partition */
        mova    ERR_PTN, r0
error:
        bsr     message_crlf
         mov    r0, r4
99:     bra     99b
         nop

read_error:
        bra     error
         mova   ERR_READ, r0

magic_error:
        bra     error
         mova   ERR_NO_BOOTXX, r0

message_crlf:
        mov     #32, r0
        trapa   #0x3f
        mova    crlf, r0
        mov     r0, r4
        mov     #32, r0
        trapa   #0x3f
        rts
         nop

read_sectors_lba:
        mov     #2, r0
        trapa   #0x3f
        tst     r0, r0
        bf      read_error
        rts
         nop

boot_lba:
        mov     #0x40, r4               /* LBA */
        mov     r9, r5                  /* LBA # */
        mov     r10, r6                 /* buffer address */
        bsr     read_sectors_lba
         mov    #BOOTXX_SECTORS, r7     /* number of sectors */

pbr_read_ok:
        mov.l   .L.bootxx_magic1, r1
        mov.l   .L.bootxx_magic, r2
        mov.l   @r2, r2
        cmp/eq  r1, r2
        bf      magic_error

        /* flush cache */
        mov     #0, r4
        mov     #6, r0
        trapa   #0x3f

        mov.l   .L.bootxx_start, r13
        jmp     @r13                    /* jump to bootxx */
         mov    r9, r4                  /* pass sector address to bootxx */


        .align  1
mbr_size:       .word   mbr_end - _C_LABEL(start)
        .align  1
stack_offset:   .word   0x1000
        .align  1
part_offset:    .word   MBR_PART_OFFSET
        .align  1
magic_offset:   .word   MBR_MAGIC_OFFSET

        .align  2
.L.bootxx_magic1:
        .long   LANDISK_BOOT_MAGIC_1
.L.bootxx_magic:
        .long   _C_LABEL(bootxx_magic)
.L.bootxx_start:
        .long   _C_LABEL(bootxx_start)

        .align  2
crlf:           .asciz  "\r\n"

        .align  2
ERR_READ:       .asciz  "Disk read"
        .align  2
ERR_NO_BOOTXX:  .asciz  "Not a bootxx image"
        .align  2
ERR_PTN:        .asciz  "No NetBSD partition"


/* space for mbr_dsn */
        . = _C_LABEL(start) + MBR_DSN_OFFSET
        .long   0

/* mbr_bootsel_magic */
        . = _C_LABEL(start) + MBR_BS_MAGIC_OFFSET
        .word   0

/*
 * MBR partition table
 */
        . = _C_LABEL(start) + MBR_PART_OFFSET
_pbr_part0:
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
_pbr_part1:
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
_pbr_part2:
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
_pbr_part3:
        .byte   0, 0, 0, 0, 0, 0, 0, 0  
        .byte   0, 0, 0, 0, 0, 0, 0, 0  

        . = _C_LABEL(start) + MBR_MAGIC_OFFSET
magic:
        .word   MBR_MAGIC
mbr_end: