1
- /****** ----- MBR-bootloader for MBR-embedding ----- ******/
2
-
3
-
4
- /*
5
-
6
- whatever the circumsance, this code MUST fit in 446 bytes
7
-
8
-
9
- */
10
-
11
-
12
- typedef unsigned long UInt32 ;
13
- typedef unsigned short UInt16 ;
14
- typedef unsigned char UInt8 ;
15
-
16
- typedef struct {
17
-
18
- UInt8 status ;
19
- UInt8 start_CHS [3 ];
20
- UInt8 type ;
21
- UInt8 end_CHS [3 ];
22
- UInt32 start_LBA ;
23
- UInt32 len_LBA ;
24
-
25
- }Part ;
26
-
27
- #define FF_base ((volatile UInt8*)0x40100000)
28
-
29
- #define FFTHR (base ) (base[0x00])
30
- #define FFIER (base ) (base[0x04])
31
- #define FFFCR (base ) (base[0x08])
32
- #define FFLCR (base ) (base[0x0C])
33
- #define FFMCR (base ) (base[0x10])
34
- #define FFLSR (base ) (base[0x14])
35
-
36
-
37
- static inline void uartInit (void ){
38
-
39
- volatile UInt8 * base = FF_base ;
40
-
41
- FFMCR (base ) = 0x00 ; //disable loopback
42
- FFLCR (base ) = 0x03 ; //8n1 mode, DLAB off
43
- FFFCR (base ) = 0x00 ; //fifos off
44
- FFIER (base ) = 0x60 ; //unit on, NRZI on, all interrupts off
45
- }
46
-
47
- static void printc (char c ){
48
-
49
- volatile UInt8 * base = FF_base ;
50
-
51
- while (!(FFLSR (base ) & 0x20 )); //wait for a spot in transmit buffer
52
- FFTHR (base ) = c ;
53
- }
54
-
55
- static void puts (const char * str ){
56
-
57
- char c ;
58
-
59
- while ((c = * str ++ ) != 0 ) printc (c );
60
- }
61
-
62
- static void err_msg (const char * err ){ //should not return
63
-
64
- puts ("MBRboot: failed to " );
65
- puts (err );
66
-
67
- while (1 );
68
- }
69
-
70
- static UInt32 read32 (const void * p ){ // FUNC: read 32-bit val aligned to 16 boundary
71
-
72
- const UInt16 * ptr = p ;
73
-
74
- return ((UInt32 )(ptr [0 ])) | (((UInt32 )(ptr [1 ])) << 16 );
75
- }
76
-
77
- static asm UInt32 doOp (UInt32 val , UInt32 subop , UInt32 index , UInt32 op ){
78
-
79
- dcd 0xBBBB469c // FUNC: { mov r12,r3; hypercall; }
80
- bx lr
81
- }
82
-
83
- static asm void __call_via_r0 (){ bx r0 }
84
- static asm void __call_via_r1 (){ bx r1 }
85
- static asm void __call_via_r2 (){ bx r2 }
86
- static asm void __call_via_r3 (){ bx r3 }
87
- static asm void __call_via_r4 (){ bx r4 }
88
- static asm void __call_via_r5 (){ bx r5 }
89
- static asm void __call_via_r6 (){ bx r6 }
90
- static asm void __call_via_r7 (){ bx r7 }
91
-
92
- static void mbrBoot (UInt32 base ){
93
-
94
- Part * p ;
95
- UInt32 i , t , x ;
96
- UInt32 * code ;
97
- void * code_ptr ;
98
-
99
- uartInit ();
100
-
101
- p = (Part * )(base + 446 );
102
-
103
- for (i = 0 ; i < 4 ; i ++ , p ++ ){
104
-
105
- if (p -> status == 0x80 ) goto found ; //small size optimization that compiler will not do for us
106
- }
107
- err_msg ("find an active partition" );
108
-
109
- found :
110
-
111
- i = read32 (& p -> len_LBA );
112
- t = read32 (& p -> start_LBA );
113
-
114
- code = (void * )(0xA0000000 + doOp (0 ,0 ,0 ,3 ) - 512 * i ); //end of ram
115
- code_ptr = code + 128 ; //one sector later is where code starts:)
116
-
117
- while (i -- ){
118
-
119
- if (!doOp (1 , t ++ , 0 , 4 )) err_msg ("read sector" );
120
- for (x = 0 ; x < 128 ; x ++ ) * code ++ = doOp (0 , x , 0 , 5 );
121
- }
122
-
123
- ((void (* )(void ))code_ptr )();
124
- }
125
-
126
- asm void __CodeRelocEnd__ (void );
127
-
128
-
129
- asm void __ARMlet_Startup__ (){
130
-
131
- mov r0 , #0xE9 //this is here to make the first few bytes look like an x86 jump - a requirement for mbr
132
-
133
- ldr r0 , = __CodeRelocEnd__ + 510 //a small stack (512 bytes of it, after that we overwrite ourselves)
134
- add r0 , pc
135
- mov sp , r0
136
-
137
- mov r0 , pc
138
- sub r0 , #12
139
- mov r10 , r0
140
-
141
- bl mbrBoot
1
+ /****** ----- MBR-bootloader for MBR-embedding ----- ******/
2
+
3
+
4
+ /*
5
+
6
+ whatever the circumsance, this code MUST fit in 446 bytes
7
+
8
+
9
+ */
10
+
11
+
12
+ typedef unsigned long UInt32 ;
13
+ typedef unsigned short UInt16 ;
14
+ typedef unsigned char UInt8 ;
15
+
16
+ typedef struct {
17
+
18
+ UInt8 status ;
19
+ UInt8 start_CHS [3 ];
20
+ UInt8 type ;
21
+ UInt8 end_CHS [3 ];
22
+ UInt32 start_LBA ;
23
+ UInt32 len_LBA ;
24
+
25
+ }Part ;
26
+
27
+ #define FF_base ((volatile UInt8*)0x40100000)
28
+
29
+ #define FFTHR (base ) (base[0x00])
30
+ #define FFIER (base ) (base[0x04])
31
+ #define FFFCR (base ) (base[0x08])
32
+ #define FFLCR (base ) (base[0x0C])
33
+ #define FFMCR (base ) (base[0x10])
34
+ #define FFLSR (base ) (base[0x14])
35
+
36
+
37
+ static inline void uartInit (void ){
38
+
39
+ volatile UInt8 * base = FF_base ;
40
+
41
+ FFMCR (base ) = 0x00 ; //disable loopback
42
+ FFLCR (base ) = 0x03 ; //8n1 mode, DLAB off
43
+ FFFCR (base ) = 0x00 ; //fifos off
44
+ FFIER (base ) = 0x60 ; //unit on, NRZI on, all interrupts off
45
+ }
46
+
47
+ static void printc (char c ){
48
+
49
+ volatile UInt8 * base = FF_base ;
50
+
51
+ while (!(FFLSR (base ) & 0x20 )); //wait for a spot in transmit buffer
52
+ FFTHR (base ) = c ;
53
+ }
54
+
55
+ static void puts (const char * str ){
56
+
57
+ char c ;
58
+
59
+ while ((c = * str ++ ) != 0 ) printc (c );
60
+ }
61
+
62
+ static void err_msg (const char * err ){ //should not return
63
+
64
+ puts ("MBRboot: failed to " );
65
+ puts (err );
66
+
67
+ while (1 );
68
+ }
69
+
70
+ static UInt32 read32 (const void * p ){ // FUNC: read 32-bit val aligned to 16 boundary
71
+
72
+ const UInt16 * ptr = p ;
73
+
74
+ return ((UInt32 )(ptr [0 ])) | (((UInt32 )(ptr [1 ])) << 16 );
75
+ }
76
+
77
+ static asm UInt32 doOp (UInt32 val , UInt32 subop , UInt32 index , UInt32 op ){
78
+
79
+ dcd 0xBBBB469c // FUNC: { mov r12,r3; hypercall; }
80
+ bx lr
81
+ }
82
+
83
+ static asm void __call_via_r0 (){ bx r0 }
84
+ static asm void __call_via_r1 (){ bx r1 }
85
+ static asm void __call_via_r2 (){ bx r2 }
86
+ static asm void __call_via_r3 (){ bx r3 }
87
+ static asm void __call_via_r4 (){ bx r4 }
88
+ static asm void __call_via_r5 (){ bx r5 }
89
+ static asm void __call_via_r6 (){ bx r6 }
90
+ static asm void __call_via_r7 (){ bx r7 }
91
+
92
+ static void mbrBoot (UInt32 base ){
93
+
94
+ Part * p ;
95
+ UInt32 i , t , x ;
96
+ UInt32 * code ;
97
+ void * code_ptr ;
98
+
99
+ uartInit ();
100
+
101
+ p = (Part * )(base + 446 );
102
+
103
+ for (i = 0 ; i < 4 ; i ++ , p ++ ){
104
+
105
+ if (p -> status == 0x80 ) goto found ; //small size optimization that compiler will not do for us
106
+ }
107
+ err_msg ("find an active partition" );
108
+
109
+ found :
110
+
111
+ i = read32 (& p -> len_LBA );
112
+ t = read32 (& p -> start_LBA );
113
+
114
+ code = (void * )(0xA0000000 + doOp (0 ,0 ,0 ,3 ) - 512 * i ); //end of ram
115
+ code_ptr = code + 128 ; //one sector later is where code starts:)
116
+
117
+ while (i -- ){
118
+
119
+ if (!doOp (1 , t ++ , 0 , 4 )) err_msg ("read sector" );
120
+ for (x = 0 ; x < 128 ; x ++ ) * code ++ = doOp (0 , x , 0 , 5 );
121
+ }
122
+
123
+ ((void (* )(void ))code_ptr )();
124
+ }
125
+
126
+ asm void __CodeRelocEnd__ (void );
127
+
128
+
129
+ asm void __ARMlet_Startup__ (){
130
+
131
+ mov r0 , #0xE9 //this is here to make the first few bytes look like an x86 jump - a requirement for mbr
132
+
133
+ ldr r0 , = __CodeRelocEnd__ + 510 //a small stack (512 bytes of it, after that we overwrite ourselves)
134
+ add r0 , pc
135
+ mov sp , r0
136
+
137
+ mov r0 , pc
138
+ sub r0 , #12
139
+ mov r10 , r0
140
+
141
+ bl mbrBoot
142
142
}
0 commit comments