blob: c4109c9963f9af1db0f6bc048a256f26fe4020c8 [file] [log] [blame]
/* First stage loader bootstrap for flash of a JavaStation.
Copyright (C) 1996,1997,2000 Jakub Jelinek
Copyright (C) 1999,2000 Pete Zaitcev
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#define BLOCK_START 0x300 /* We are not a.out, so can use anything */
#include "ieee32.h" /* IEEE32_OFFSET */
#define LOAD_OFF 1024 /* Skip PROM interface buffer */
#define buffer %l3
#define dest %l4
#define promvec %l5
#define fd %l6
#define stdouth %l7
.text
.align 4
.global _start
_start:
ba 1f
sethi %hi(0x4000), buffer
.ascii IMGVERSION
1: sethi %hi(0x10000), dest
mov %o3, promvec
add buffer, %lo(chosen), %o1
call prom11
add buffer, %lo(finddevice), %o0
ld [dest + 16], fd
call getprop
add buffer, %lo(stdout), %o0
ld [dest + 256], stdouth
call putchar
mov 'S', %o0
/*
* Get phandle of flash memory.
* Unlike other first stage loaders
* we do not use "/chosen"."bootpath" value.
* It's a feature, not a bug.
*/
add buffer, %lo(flashs), %o1
call prom11
add buffer, %lo(finddevice), %o0
ld [dest + 16], fd /* phandle of /flash-memory */
/*
* Get "reg". We use it to find the base address,
* which is different for 4MB, 8MB and 16MB SIMMs.
*/
call getprop
add buffer, %lo(regs), %o0
ld [dest + 260], %i2 /* 20400000 for 8MB SIMM */
/*
* Load 4 blocks of second stage loader with the map,
* then all other blocks at 0x10000 (dest).
* First of them will have an 'L' header embedded.
*/
or buffer, BLOCK_START, %l1
add %l1, (3 * 512), %i5 /* Will read 4 blocks of block map */
mov %l1, %l2
/*
* But before we start the loop, get the block 0 number.
* In other loaders we get it for free when 16 blocks of
* bootstrap are loaded. In flash it is outside of ELF.
*/
add %i2, IEEE32_OFFSET, %i4
lda [%i4] 0x20, %i3
st %i3, [%l2]
5:
ld [%l2], %i3
subcc %i3, 0, %g0
add %l2, 4, %l2
bz 7f
sll %i3, 9, %o3 /* Convert blocks into bytes */
/* srl %i3, 23, %o2 */ /* %o2 and %o3 make an 41 bits offset */
/*
* blkblt
* We use ASI=20 (BYPASS) to spare remapping work. Lazy, but works.
* We do not unroll the loop because flash is slow and RAM is tight.
*/
mov 512, %i0 /* running cnt */
mov %l1, %i1 /* running dest */
add %i2, %o3, %i4 /* running source (physical addr) */
/* We conviniently ignore upper bits of offset for flash is small. */
1:
lda [%i4] 0x20, %i3
st %i3, [%i1]
add %i4, 4, %i4
add %i1, 4, %i1
subcc %i0, 4, %i0
bne 1b
nop
cmp %l1, %i5
bne 5b
add %l1, 512, %l1
call putchar
mov 'I', %o0
b 5b
add dest, LOAD_OFF, %l1
7:
ldub [dest + LOAD_OFF + 0x08], %o0
cmp %o0, 'L'
bne exit
nop
call putchar
nop
/* flush dest + LOAD_OFF */ /* XXX Write-through cache on IIep */
clr %o4 /* Important - not Ultra */
or promvec, 1, %o0 /* XXX Gross... */
clr %o3 /* Hmm... */
jmpl dest + LOAD_OFF, %g0
clr %l3
exit:
add buffer, %lo(exits), %o0
call prom11
st %o0, [dest + 16]
/*
* getprop(node:fd, name:%o0) {
* cif_handler:promvec("getprops", node, name, dest+256, 1024);
* }
*/
getprop:
add buffer, %lo(getprops), %o2
st %o2, [dest]
mov 4, %o2
st %o2, [dest + 4]
mov 1, %o2
st %o2, [dest + 8]
st fd, [dest + 12]
st %o0, [dest + 16]
add dest, 256, %o0
st %o0, [dest + 20]
mov 1024, %o0
st %o0, [dest + 24]
jmpl promvec + %g0, %g0
mov dest, %o0
/*
*/
putchar:
stb %o0, [buffer]
mov stdouth, %o1
mov buffer, %o2
mov 1, %o3
ba prom31 /* one of many tail recustion -O's */
add buffer, %lo(write), %o0
/*
* One in, one out.
*/
prom11:
st %o0, [dest]
mov 1, %o2
st %o2, [dest + 4]
st %o2, [dest + 8]
st %o1, [dest + 12]
jmpl promvec + %g0, %g0
mov dest, %o0
/*
* Three in, one out.
*/
prom31:
st %o0, [dest]
mov 3, %o4
st %o4, [dest + 4]
mov 1, %o4
st %o4, [dest + 8]
st %o1, [dest + 12]
st %o2, [dest + 16]
st %o3, [dest + 20]
jmpl promvec + %g0, %g0
mov dest, %o0
finddevice:
.asciz "finddevice"
getprops:
.asciz "getprop"
stdout:
.asciz "stdout"
write:
.asciz "write"
chosen:
.asciz "/chosen"
exits:
.asciz "exit"
flashs:
.asciz "/flash-memory"
regs:
.asciz "reg"