6
6
Copyright (C) 2006 Marc Singer
8
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of the GNU General Public License as
10
published by the Free Software Foundation; either version 2 of the
11
License, or (at your option) any later version.
13
This program is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
9
modify it under the terms of the GNU General Public License
10
version 2 as published by the Free Software Foundation.
11
Please refer to the file debian/copyright for further details.
30
20
the ATAGS and the machine type in the EXTREME circumstance that the
31
21
platform bootloader cannot be replaced.
26
Because we don't know where we're going to be executing, we do a
27
little shenanigans to figure out the execution offset. With it, we
28
can reference data that was fixed-up with an absolute address even
29
though we are not executing from that address.
34
This code can be used with either big or little endian kernels, and
35
it can be used to switch the endan-ness of the system from the
36
boot-up default to the desired orientation for the kernel.
37
However, you must swap the bytes of this file and the kernel if you
38
are going to write this data to flash.
38
45
#include "types.h" /* include/asm-arm/types.h */
39
46
#include "setup.h" /* include/asm-arm/setup.h */
41
#define H_SIZE(pv) (((struct tag_header*)pv)->size)
42
#define H_TAG(pv) (((struct tag_header*)pv)->tag)
44
#define P_CORE(pv) ((struct tag_core*)(pv + sizeof (struct tag_header)))
45
#define P_MEM32(pv) ((struct tag_mem32*)(pv + sizeof (struct tag_header)))
46
#define P_CMDLINE(pv) ((struct tag_cmdline*)(pv + sizeof (struct tag_header)))
48
48
#define NAKED __attribute__((naked))
49
#define BOOT __attribute__((section(".boot")))
50
51
#if defined (COMMANDLINE)
51
const char __attribute__((section(".rodata"))) cmdline[] = COMMANDLINE;
52
const char cmdline[] = COMMANDLINE;
54
void NAKED __attribute__((section(".boot"))) boot (u32 r0, u32 r1, u32 r2)
56
void NAKED BOOT boot (u32 r0, u32 r1, u32 r2)
56
__asm volatile (" nop");
58
__asm volatile ("nop"); /* Require to get compiler to jump here */
59
61
int NAKED start (void)
62
extern char SHIM_VMA_END;
64
extern unsigned long reloc;
65
unsigned long offset = (unsigned long) &reloc;
64
67
#if defined (FORCE_BIGENDIAN)
84
pv = (void*) PHYS_PARAMS;
87
__asm volatile ("bl reloc\n\t"
88
"reloc: sub %0, lr, %0\n\t"
93
#if defined (IXP4XX_SDR_CONFIG)
94
*(volatile unsigned long*) 0xcc000000 = IXP4XX_SDR_CONFIG;
97
#if defined (CREATE_ATAGS) && defined (PHYS_PARAMS)
98
p = (struct tag*) PHYS_PARAMS;
86
100
/* Always start with the CORE tag */
87
H_SIZE(pv) = tag_size (tag_core);
88
H_TAG(pv) = ATAG_CORE;
89
P_CORE(pv)->flags = 0;
90
P_CORE(pv)->pagesize = 0;
91
P_CORE(pv)->rootdev = 0;
101
p->hdr.tag = ATAG_CORE;
102
p->hdr.size = tag_size (tag_core);
104
p->u.core.pagesize = 0;
105
p->u.core.rootdev = 0;
94
108
/* Memory tags are always second */
95
H_SIZE(pv) = tag_size (tag_mem32);
97
P_MEM32(pv)->size = RAM_BANK0_LENGTH;
98
P_MEM32(pv)->start = RAM_BANK0_START;
101
#if defined (RAM_BANK1_START)
102
H_SIZE(pv) = tag_size (tag_mem32);
103
H_TAG(pv) = ATAG_MEM;
104
P_MEM32(pv)->size = RAM_BANK1_LENGTH;
105
P_MEM32(pv)->start = RAM_BANK1_START;
109
p->hdr.tag = ATAG_MEM;
110
p->hdr.size = tag_size (tag_mem32);
111
p->u.mem.size = RAM_BANK0_LENGTH;
112
p->u.mem.start = RAM_BANK0_START;
115
# if defined (RAM_BANK1_START)
116
p->hdr.tag = ATAG_MEM;
117
p->hdr.size = tag_size (tag_mem32);
118
p->u.mem.size = RAM_BANK1_LENGTH;
119
p->u.mem.start = RAM_BANK1_START;
123
# if defined (INITRD_START)
124
p->hdr.tag = ATAG_INITRD2;
125
p->hdr.size = tag_size (tag_initrd);
126
p->u.initrd.start = INITRD_START;
127
p->u.initrd.size = INITRD_LENGTH;
109
131
/* Command line */
110
#if defined (COMMANDLINE)
111
H_SIZE(pv) = tag_size(tag_cmdline) + (sizeof (cmdline)+1+3)/4;
112
H_TAG(pv) = ATAG_CMDLINE;
132
# if defined (COMMANDLINE)
133
p->hdr.tag = ATAG_CMDLINE;
134
p->hdr.size = tag_size (tag_cmdline)
135
+ (sizeof (cmdline)+3)/4 - 1;
137
const char* sz = cmdline + offset;
115
139
for (i = 0; i < sizeof (cmdline); ++i)
116
P_CMDLINE(pv)->cmdline[i] = cmdline[i];
140
p->u.cmdline.cmdline[i] = sz[i];
123
H_TAG(pv) = ATAG_NONE;
125
/* Pass control to the kernel */
146
p->hdr.tag = ATAG_NONE;
151
#if !defined (CREATE_ATAGS) && defined (GUARANTEE_ATAG_CMDLINE)\
152
&& defined (PHYS_PARAMS) && defined (COMMANDLINE)
155
char* cmdlineFound = 0;
156
for_each_tag (p, (struct tag*) PHYS_PARAMS)
157
if (p->hdr.tag == ATAG_CMDLINE)
158
cmdlineFound = p->u.cmdline.cmdline;
160
/* The pointer p is left at the start of the terminating
161
ATAG_NONE. If cmdlineFound is non-null, we've found an
162
instance of the ATAG_CMDLINE. If not, we append the default
163
command line and a new ATAG_NONE.
165
The original author was concerned about the possibility that
166
there may be more than one ATAG_CMDLINE record. There is no
167
stipulation in the documentation for the cmdline tags, but it
168
makes sense that there would be only one. Even if there were
169
more than one, I'm not sure it would matter since we won't
170
append one if we find any. */
172
if (!cmdlineFound || !*cmdlineFound) {
173
p->hdr.tag = ATAG_CMDLINE;
174
p->hdr.size = tag_size (tag_cmdline)
175
+ (sizeof (cmdline)+3)/4 - 1;
177
const char* sz = cmdline + offset;
179
for (i = 0; i < sizeof (cmdline); ++i)
180
p->u.cmdline.cmdline[i] = sz[i];
183
p->hdr.tag = ATAG_NONE;
190
/* Pass control to the kernel. The compile ought to optimize
191
this to a branch (instead of a branch-link), but it doesn't
192
matter if it doesn't. */
126
193
boot (0, MACH_TYPE, PHYS_PARAMS);