summaryrefslogtreecommitdiffstats
path: root/arch/sparc/boot
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /arch/sparc/boot
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'arch/sparc/boot')
-rw-r--r--arch/sparc/boot/Makefile12
-rw-r--r--arch/sparc/boot/README21
-rw-r--r--arch/sparc/boot/bare.S160
-rw-r--r--arch/sparc/boot/bare.h18
-rw-r--r--arch/sparc/boot/empirical.h8
-rw-r--r--arch/sparc/boot/init_me.c69
6 files changed, 288 insertions, 0 deletions
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
new file mode 100644
index 000000000..b9d54e652
--- /dev/null
+++ b/arch/sparc/boot/Makefile
@@ -0,0 +1,12 @@
+# $Id: Makefile,v 1.3 1996/08/04 08:40:58 ecd Exp $
+# Makefile for the Sparc low level /boot module.
+#
+# Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+
+all: boot
+
+boot:
+ @echo "Nothing special to be done for 'boot' on Linux/SPARC."
+
+dep:
+
diff --git a/arch/sparc/boot/README b/arch/sparc/boot/README
new file mode 100644
index 000000000..189a72d29
--- /dev/null
+++ b/arch/sparc/boot/README
@@ -0,0 +1,21 @@
+This directory will contain the code necessary to compile and link the
+/boot program which is necessary to boot on the Sparc. This program
+is real ugly and it knows too much. It must be able to not only boot
+off of the root partition but also be able to netboot. This means
+that it knows about RPC and NFS (bleech, yuck, eeewwwww!!) so that it
+can remote mount the root directory to fetch the kernel. Also it must
+be able to ARP for its IP address and who its boot server is. I
+think I'm getting sick.
+
+Regardless for now I will concentrate on the low-level stuff necessary
+to get the thing going. This means the low-level entry code, etc.
+The prom knows how to get "us" if we have the proper boot blocks,
+actually the boot blocks live in our logical partition on a hard drive
+whereas over NFS this isn't applicable. We have the boot blocks in
+our data area either way because we can be dual purpose.
+
+More will come....
+
+Hopefully I can write this such that it will work on almost all SUN
+machines in existence. We'll see ;(
+
diff --git a/arch/sparc/boot/bare.S b/arch/sparc/boot/bare.S
new file mode 100644
index 000000000..ab3508591
--- /dev/null
+++ b/arch/sparc/boot/bare.S
@@ -0,0 +1,160 @@
+/* $Id: bare.S,v 1.4 1996/04/23 01:53:40 davem Exp $
+ * base.S: Ugly low-level boot program entry code. The job of this
+ * module is to parse the boot flags, try to mount the remote
+ * root filesystem and load the kernel into virtual memory.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include "bare.h"
+#include <asm/ptrace.h>
+
+ .data
+ .globl C_LABEL(romvec)
+ .globl C_LABEL(idp_ptr)
+
+C_LABEL(romvec):
+ .word 0
+C_LABEL(idp_ptr):
+ .word 0
+
+ .text
+ .align 8
+ .globl C_LABEL(first_adr_in_text)
+
+C_LABEL(first_adr_in_text):
+
+ /* Grrr, boot block, scratching my head... */
+ .globl C_LABEL(b_block) /* Start of actual boot block */
+ .globl C_LABEL(b_block_size) /* In bytes */
+ .globl C_LABEL(b_block_cksum) /* Checksum of boot block bytes */
+
+ b start_of_execution /* XXX Hack */
+ nop
+
+ .align 8
+C_LABEL(b_block):
+ .skip (BOOTBLOCK_NENTRIES * BOOTBLOCK_ENTSIZE)
+
+C_LABEL(b_block_size):
+ .word 0
+
+C_LABEL(b_block_cksum):
+ .word 0
+
+/* Ok, the prom has left in %o0 the PROM pointer. We leave it here
+ * for when we jump into the kernel. So save out of this window before
+ * you dick with %o0. As far as I know we could be loaded *anywhere*, so
+ * we relocate ourselves to the "linked" location. Self modifying code rules.
+ */
+
+start_of_execution:
+ sethi %hi(C_LABEL(first_adr_in_text)), %o1 ! This is our top
+ or %o1, %lo(C_LABEL(first_adr_in_text)), %o1 ! of stack too.
+ sub %o1, REGWIN_SZ, %o1
+ add %o1, 0x7, %o1
+ andn %o1, 0x7, %o1
+ save %o1, 0x0, %sp ! save is an add
+here:
+ call there
+ sethi %hi(here), %o4
+there:
+ sub %o7, here-C_LABEL(first_adr_in_text), %o5
+ or %o4, %lo(here), %o4
+ cmp %o4, %o7
+ be loaded_ok
+ nop
+
+ /* Gotta relocate, compute our size sans bss segment. */
+ set C_LABEL(edata)+4, %o3
+ set C_LABEL(first_adr_in_text), %o2
+ sub %o3, %o2, %o3
+rel_loop:
+ ld [%o5], %o4
+ add %o5, 0x4, %o5
+ st %o4, [%o2]
+ subcc %o3, 0x4, %o3
+ bg rel_loop
+ add %o2, 0x4, %o2
+
+ /* Pray that we are now in a sane place in memory */
+ sethi %hi(loaded_ok), %o2
+ or %o2, %lo(loaded_ok), %o2
+ jmp %o2
+ nop
+
+loaded_ok:
+ /* Save the PROM pointer */
+ sethi %hi(C_LABEL(romvec)), %o1
+ or %o1, %lo(C_LABEL(romvec)), %o1
+ st %i0, [%o1]
+
+ /* Build a PSR we can live with */
+ rd %psr, %o1
+
+#if 0
+ andn %o1, PSR_PIL, %o1
+ sethi %hi(SANE_PSR), %g4
+ or %g4, %lo(SANE_PSR), %g4
+ or %o1, %g4, %o1
+#endif
+
+ /* V8 book says this works to calculate num_windows */
+ sethi %hi(0xffffffff), %g2
+ rd %wim, %g3
+ or %g2, %lo(0xffffffff), %g2
+ wr %g2, 0x0, %wim
+ WRITE_PAUSE
+
+ rd %wim, %g4
+ WRITE_PAUSE
+
+ wr %g3, 0x0, %wim
+ WRITE_PAUSE
+
+ /* Restore old %psr */
+ wr %o1, 0x0, %psr
+ WRITE_PAUSE
+
+ or %g0, 0x0, %g3
+1:
+ srl %g4, 0x1, %g4
+ subcc %g4, 0x0, %g0
+ bne 1b
+ add %g3, 0x1, %g3
+
+ /* %g3 now contains nwindows */
+ sethi %hi(C_LABEL(nwindows)), %o4
+ st %g3, [%o4 + %lo(C_LABEL(nwindows))]
+
+ /* Now zero out our bss segment, lord knows the nasty prom monster
+ * didn't do it for us.
+ */
+ sethi %hi(C_LABEL(end)), %g1
+ or %g1, %lo(C_LABEL(end)), %g1
+ add %g1, 0x4, %g1
+ sethi %hi(C_LABEL(edata)), %g2
+ or %g2, %lo(C_LABEL(edata)), %g2
+
+ /* Slow, inefficient, who cares, this is messy boot code */
+bzero_bss_loop:
+ st %g0, [%g2]
+ add %g2, 0x4, %g2
+ cmp %g2, %g1
+ bl bzero_bss_loop
+ nop
+
+ call C_LABEL(init_me) ! Fun with empirical constants and prom
+ nop
+
+ /* Dump back into the prom */
+get_me_out_of_here:
+ set C_LABEL(romvec), %g2
+ ld [%g2], %g2
+ ld [%g2 + 0x74], %g2
+ restore
+ call %g2
+ nop
+
+
+
diff --git a/arch/sparc/boot/bare.h b/arch/sparc/boot/bare.h
new file mode 100644
index 000000000..b84178c45
--- /dev/null
+++ b/arch/sparc/boot/bare.h
@@ -0,0 +1,18 @@
+/* $Id: bare.h,v 1.2 1995/11/25 00:57:41 davem Exp $
+ * bare.h: Defines for the low level entry code of the BOOT program.
+ * We include in the head.h stuff that the real kernel uses
+ * and this saves a lot of repetition here.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/head.h>
+#include <asm/psr.h>
+#include <asm/cprefix.h>
+
+#define SANE_PIL (0xd00) /* No interrupts except clock and unmaskable NMI's */
+#define SANE_PSR (SANE_PIL|PSR_S|PSR_ET)
+
+#define BOOTBLOCK_NENTRIES 0x40 /* Number of entries in the boot block */
+#define BOOTBLOCK_ENTSIZE 0x04 /* Size in bytes of each boot block entry */
+
diff --git a/arch/sparc/boot/empirical.h b/arch/sparc/boot/empirical.h
new file mode 100644
index 000000000..e13b8c80a
--- /dev/null
+++ b/arch/sparc/boot/empirical.h
@@ -0,0 +1,8 @@
+/* $Id: empirical.h,v 1.2 1996/04/23 01:53:42 davem Exp $
+ * empirical.h: Nasty hacks....
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#define DEF_BOGO 25
+
diff --git a/arch/sparc/boot/init_me.c b/arch/sparc/boot/init_me.c
new file mode 100644
index 000000000..ad26a1969
--- /dev/null
+++ b/arch/sparc/boot/init_me.c
@@ -0,0 +1,69 @@
+/* $Id: init_me.c,v 1.3 1996/04/21 10:30:09 davem Exp $
+ * init_me.c: Initialize empirical constants and gather some info from
+ * the boot prom.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/openprom.h> /* For property declarations and the prom structs */
+#include <asm/oplib.h>
+#include <asm/vac-ops.h>
+
+#include "empirical.h" /* Don't ask... */
+
+#define DEBUG_INIT_ME /* Tell me what's going on */
+
+unsigned int nwindows; /* Set in bare.S */
+unsigned int nwindowsm1;
+unsigned int pac_or_vac; /* 0 means "dunno" 1 means "VAC" 2 means "PAC" */
+unsigned int pvac_size; /* Use the same two variables for a PAC and VAC */
+unsigned int pvac_linesize;
+unsigned int pac_size;
+int num_segmaps;
+int num_contexts;
+unsigned int BOGOMIPS; /* bogosity without the VAC cache on */
+unsigned int BOGOMIPS_WCACHE; /* bogosity with the VAC cache */
+unsigned int delay_factor;
+
+extern int prom_node_root;
+void (*printk)(const char *str, ...);
+
+void init_me(void)
+{
+ unsigned int grrr;
+
+ printk = romvec->pv_printf;
+ prom_node_root = prom_nextnode(0);
+ prom_getprop(prom_node_root, "mmu-npmg", &num_segmaps,
+ sizeof(unsigned int));
+
+ pvac_size = prom_getint_default(prom_node_root, "vac-size", 65536);
+
+ pvac_linesize = prom_getint_default(prom_node_root, "vac-linesize", 16);
+
+ grrr = prom_getint_default(prom_node_root, "mips-on", 0);
+ if(!grrr) {
+ grrr = prom_getint_default(prom_node_root, "clock-frequency", 0);
+ if(grrr > 15000000 && grrr < 100000000) {
+ BOGOMIPS = 3;
+ BOGOMIPS_WCACHE = grrr / 1000000;
+ } else {
+ BOGOMIPS = DEF_BOGO;
+ BOGOMIPS_WCACHE = DEF_BOGO;
+ }
+ } else (BOGOMIPS_WCACHE = grrr,
+ BOGOMIPS = prom_getint(prom_node_root, "mips-off"));
+
+#ifdef DEBUG_INIT_ME
+ (*(romvec->pv_printf))("\nBOGOMIPS %d\n", (int) BOGOMIPS);
+ (*(romvec->pv_printf))("BOGOMIPS_WCACHE %d\n", (int) BOGOMIPS_WCACHE);
+ (*(romvec->pv_printf))("pvac_size %d\n", (int) pvac_size);
+ (*(romvec->pv_printf))("pvac_linesize %d\n", (int) pvac_linesize);
+ (*(romvec->pv_printf))("num_segmaps %d\n", (int) num_segmaps);
+#endif
+
+ delay_factor = (BOGOMIPS > 3) ? ((BOGOMIPS - 2) >> 1) : 11;
+
+ (*(romvec->pv_printf))("\nLILO: \n");
+ return;
+}