annotate loader/loader/loader_c.c @ 683:4fa3b09faa14

loader: do not duplicate ccw and orb definitions Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 06 Aug 2019 10:28:29 -0400
parents 45bec12c305f
children 9de638d13941
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
1 /*
640
45bec12c305f Convert non-tools build system to plain old makefiles (bmake-flavor)
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 593
diff changeset
2 * Copyright (c) 2007-2019 Josef 'Jeff' Sipek
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
3 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
4
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
5 #include "loader.h"
683
4fa3b09faa14 loader: do not duplicate ccw and orb definitions
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 640
diff changeset
6 #include <channel.h>
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
7 #include <binfmt_elf.h>
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
8
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
9 static unsigned char seek_data[6];
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
10 static unsigned char search_data[5];
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
11 static struct ccw ccw[4];
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
12
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
13 struct orb ORB = {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
14 .param = 0x12345678,
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
15 .f = 1,
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
16 .lpm = 0xff,
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
17 .addr = 0xffffffff,
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
18 };
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
19
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
20 static u8 *buf = (u8*) (16 * 1024);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
21 static u32 *ptrbuf = (u32*) (20 * 1024);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
22
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
23 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
24 * halt the cpu
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
25 *
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
26 * NOTE: we don't care about not clobbering registers as when this
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
27 * code executes, the CPU will be stopped.
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
28 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
29 static inline void die(void)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
30 {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
31 asm volatile(
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
32 "SR %r1, %r1 # not used, but should be zero\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
33 "SR %r3, %r3 # CPU Address\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
34 "SIGP %r1, %r3, 0x05 # Signal, order 0x05\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
35 );
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
36
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
37 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
38 * Just in case SIGP fails
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
39 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
40 for(;;);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
41 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
42
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
43 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
44 * determine amount of storage
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
45 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
46 static u64 sense_memsize(void)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
47 {
640
45bec12c305f Convert non-tools build system to plain old makefiles (bmake-flavor)
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 593
diff changeset
48 volatile u64 *pgm_psw = (void *) 0x1d0;
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
49 u64 size;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
50 int cc;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
51
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
52 #define SKIP_SIZE (1024*1024ULL)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
53
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
54 /* set new PGM psw */
640
45bec12c305f Convert non-tools build system to plain old makefiles (bmake-flavor)
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 593
diff changeset
55 pgm_psw[0] = 0x0000000180000000ULL;
45bec12c305f Convert non-tools build system to plain old makefiles (bmake-flavor)
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 593
diff changeset
56 pgm_psw[1] = (u64) &PGMHANDLER;
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
57
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
58 for(size = 0; size < ((u64)~SKIP_SIZE)-1; size += SKIP_SIZE) {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
59 asm volatile(
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
60 "lg %%r1,%1\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
61 "tprot 0(%%r1),0\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
62 "ipm %0\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
63 "srl %0,28\n"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
64 : /* output */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
65 "=d" (cc)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
66 : /* input */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
67 "m" (size)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
68 : /* clobber */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
69 "cc", "r1"
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
70 );
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
71
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
72 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
73 * we cheat here a little...if we try to tprot a location
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
74 * that isn't part of the configuration, a program exception
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
75 * fires off, but our handler sets the CC to 3, and resumes
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
76 * execution
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
77 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
78 if (cc == 3)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
79 break;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
80 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
81
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
82 /* invalidate new PGM psw */
640
45bec12c305f Convert non-tools build system to plain old makefiles (bmake-flavor)
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 593
diff changeset
83 memset((void *) pgm_psw, 0, 16);
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
84
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
85 return size;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
86 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
87
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
88 static void read_blk(void *ptr, u32 lba)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
89 {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
90 u16 cc, hh, r;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
91
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
92 if (lba < 1)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
93 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
94
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
95 memset(ccw, 0, sizeof(ccw));
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
96
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
97 lba--;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
98 cc = lba / RECORDS_PER_CYL;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
99 hh = (lba % RECORDS_PER_CYL) / RECORDS_PER_TRACK;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
100 r = (lba % RECORDS_PER_CYL) % RECORDS_PER_TRACK;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
101 r++;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
102
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
103 ORB.addr = ADDR31(ccw);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
104
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
105 /* SEEK */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
106 ccw[0].cmd = 0x07;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
107 ccw[0].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
108 ccw[0].count = 6;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
109 ccw[0].addr = ADDR31(seek_data);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
110
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
111 seek_data[0] = 0; /* zero */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
112 seek_data[1] = 0; /* zero */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
113 seek_data[2] = cc >> 8; /* Cc */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
114 seek_data[3] = cc & 0xff; /* cC */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
115 seek_data[4] = hh >> 8; /* Hh */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
116 seek_data[5] = hh & 0xff; /* hH */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
117
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
118 /* SEARCH */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
119 ccw[1].cmd = 0x31;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
120 ccw[1].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
121 ccw[1].count = 5;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
122 ccw[1].addr = ADDR31(search_data);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
123
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
124 search_data[0] = cc >> 8;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
125 search_data[1] = cc & 0xff;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
126 search_data[2] = hh >> 8;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
127 search_data[3] = hh & 0xff;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
128 search_data[4] = r;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
129
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
130 /* TIC */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
131 ccw[2].cmd = 0x08;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
132 ccw[2].flags = 0;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
133 ccw[2].count = 0;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
134 ccw[2].addr = ADDR31(&ccw[1]);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
135
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
136 /* READ DATA */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
137 ccw[3].cmd = 0x86;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
138 ccw[3].flags = 0;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
139 ccw[3].count = 4096;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
140 ccw[3].addr = ADDR31(ptr);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
141
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
142 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
143 * issue IO
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
144 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
145 __do_io();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
146 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
147
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
148 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
149 * read the entire nucleus into TEMP_BASE
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
150 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
151 static inline void readnucleus(void)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
152 {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
153 struct ADT *ADT = (struct ADT*) buf;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
154 struct FST *FST = (struct FST*) buf;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
155 struct FST fst;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
156 int i, found;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
157 u32 nfst;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
158
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
159 read_blk(buf, EDF_LABEL_BLOCK_NO);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
160
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
161 if ((ADT->IDENT != __ADTIDENT) ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
162 (ADT->DBSIZ != EDF_SUPPORTED_BLOCK_SIZE) ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
163 (ADT->OFFST != 0) ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
164 (ADT->FSTSZ != sizeof(struct FST)))
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
165 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
166
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
167 nfst = ADT->NFST;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
168
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
169 read_blk(buf, ADT->DOP);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
170
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
171 if (FST->NLVL != 0)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
172 die(); // FIXME
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
173
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
174 for(i=0,found=0; i<nfst; i++) {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
175 if ((!memcmp(FST[i].FNAME, CP_FN, 8)) &&
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
176 (!memcmp(FST[i].FTYPE, CP_FT, 8))) {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
177 memcpy(&fst, &FST[i], sizeof(struct FST));
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
178 found = 1;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
179 break;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
180 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
181 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
182
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
183 if (!found)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
184 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
185
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
186 if (fst.PTRSZ != 4 ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
187 fst.LRECL != 4096 ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
188 fst.RECFM != FSTDFIX)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
189 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
190
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
191 /* Don't allow more than 3MB to be read */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
192 if ((FST->AIC * FST->LRECL) > (3ULL * 1024 * 1024))
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
193 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
194
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
195 /* Since we're assuming that NLVL==1, there's only 1 pointer block */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
196 read_blk(ptrbuf, fst.FOP);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
197
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
198 /* Read all the blocks pointed to by the ptr block */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
199 for(i=0; i<fst.AIC; i++)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
200 read_blk(TEMP_BASE + (4096 * i), ptrbuf[i]);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
201 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
202
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
203 void load_nucleus(void)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
204 {
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
205 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
206 * These are all stored in registers
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
207 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
208 register u32 iplsch;
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
209 register int i, j;
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
210 register Elf64_Ehdr *nucleus_elf;
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
211 register Elf64_Shdr *section, *link_section, *tmp_section;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
212 register Elf64_Phdr *segment;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
213 register Elf64_Ehdr *elfcpy;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
214 register unsigned char *symtab;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
215 register void (*start_sym)(u64, u32, void*);
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
216
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
217 /* Save the IPL device subchannel id */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
218 iplsch = *((u32*) 0xb8);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
219
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
220 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
221 * Read entire ELF to temporary location
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
222 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
223 readnucleus();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
224
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
225 nucleus_elf = (Elf64_Ehdr*) TEMP_BASE;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
226
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
227 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
228 * Check that this looks like a valid ELF
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
229 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
230 if (nucleus_elf->e_ident[0] != '\x7f' ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
231 nucleus_elf->e_ident[1] != 'E' ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
232 nucleus_elf->e_ident[2] != 'L' ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
233 nucleus_elf->e_ident[3] != 'F' ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
234 nucleus_elf->e_ident[EI_CLASS] != ELFCLASS64 ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
235 nucleus_elf->e_ident[EI_DATA] != ELFDATA2MSB ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
236 nucleus_elf->e_ident[EI_VERSION] != EV_CURRENT ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
237 nucleus_elf->e_type != ET_EXEC ||
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
238 nucleus_elf->e_machine != 0x16 || // FIXME: find the name for the #define
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
239 nucleus_elf->e_version != EV_CURRENT)
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
240 die();
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
241
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
242 /* Iterate through each program header, and copy all PT_LOAD
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
243 * segments to the final destinations.
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
244 */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
245
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
246 for(i=0; i<nucleus_elf->e_phnum; i++) {
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
247 segment = (Elf64_Phdr*) (TEMP_BASE +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
248 nucleus_elf->e_phoff +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
249 nucleus_elf->e_phentsize * i);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
250
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
251 if (segment->p_type != PT_LOAD)
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
252 continue;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
253
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
254 if (segment->p_filesz)
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
255 memcpy((void*) segment->p_vaddr,
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
256 TEMP_BASE + segment->p_offset,
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
257 segment->p_filesz);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
258
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
259 if (segment->p_filesz != segment->p_memsz)
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
260 memset((void*) (segment->p_vaddr + segment->p_filesz),
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
261 0, segment->p_memsz - segment->p_filesz);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
262 }
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
263
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
264 /*
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
265 * Copy over the ELF header & tweak it.
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
266 */
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
267 symtab = SYMTAB_BASE;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
268 elfcpy = (Elf64_Ehdr*) symtab;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
269 memcpy(elfcpy, nucleus_elf, nucleus_elf->e_ehsize);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
270 symtab += nucleus_elf->e_ehsize;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
271
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
272 /* the program headers start right after */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
273 elfcpy->e_phoff = symtab - SYMTAB_BASE;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
274
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
275 /* copy over all the program headers */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
276 memcpy(symtab, TEMP_BASE + nucleus_elf->e_phoff,
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
277 nucleus_elf->e_phentsize * nucleus_elf->e_phnum);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
278 symtab += nucleus_elf->e_phentsize * nucleus_elf->e_phnum;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
279
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
280 /* the section headers start right after */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
281 elfcpy->e_shoff = symtab - SYMTAB_BASE;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
282
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
283 /*
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
284 * Iterate through each section to find the .symtab & .strtab (as
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
285 * well as the null section), and copy the the headers over
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
286 */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
287 elfcpy->e_shnum = 0;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
288
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
289 for(i=0; i<nucleus_elf->e_shnum; i++) {
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
290 section = (Elf64_Shdr*) (TEMP_BASE +
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
291 nucleus_elf->e_shoff +
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
292 nucleus_elf->e_shentsize * i);
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
293
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
294 switch (section->sh_type) {
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
295 case SHT_STRTAB:
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
296 if (i == nucleus_elf->e_shstrndx)
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
297 elfcpy->e_shstrndx = elfcpy->e_shnum;
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
298
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
299 case SHT_NULL:
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
300 case SHT_SYMTAB:
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
301 memcpy(symtab, section, nucleus_elf->e_shentsize);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
302 elfcpy->e_shnum++;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
303 symtab += nucleus_elf->e_shentsize;
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
304 break;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
305 default:
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
306 /* Ignoring */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
307 break;
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
308 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
309 }
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
310
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
311 for(i=0; i<elfcpy->e_shnum; i++) {
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
312 section = (Elf64_Shdr*) (SYMTAB_BASE +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
313 elfcpy->e_shoff +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
314 elfcpy->e_shentsize * i);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
315
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
316 if (!section->sh_link)
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
317 continue;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
318
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
319 tmp_section = (Elf64_Shdr*) (TEMP_BASE +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
320 nucleus_elf->e_shoff +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
321 nucleus_elf->e_shentsize *
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
322 section->sh_link);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
323
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
324 for(j=0; j<elfcpy->e_shnum; j++) {
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
325 link_section = (Elf64_Shdr*) (SYMTAB_BASE +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
326 elfcpy->e_shoff +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
327 elfcpy->e_shentsize * j);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
328
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
329 if (memcmp(tmp_section, link_section, elfcpy->e_shentsize))
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
330 continue;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
331
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
332 section->sh_link = j;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
333 break;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
334 }
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
335 }
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
336
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
337 /*
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
338 * Now that we know what sections and where, let's copy those over
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
339 */
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
340 for (i=1; i<elfcpy->e_shnum; i++) {
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
341 section = (Elf64_Shdr*) (SYMTAB_BASE +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
342 elfcpy->e_shoff +
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
343 elfcpy->e_shentsize * i);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
344
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
345 memcpy(symtab, TEMP_BASE + section->sh_offset,
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
346 section->sh_size);
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
347 section->sh_offset = symtab - SYMTAB_BASE;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
348 symtab += section->sh_size;
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
349 }
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
350
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
351 /*
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
352 * Now, jump to the nucleus entry point
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
353 */
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
354 start_sym = (void*) nucleus_elf->e_entry;
593
23c7ac98d616 Load & use symbol table
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents: 440
diff changeset
355 start_sym(sense_memsize(), iplsch, SYMTAB_BASE);
440
b4e29204291c loader: replace the existing ipl code (rdr & tape) with an EDF one
Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
parents:
diff changeset
356 }