Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/arm/boot/compressed/ofw-shark.c | |
3 | * | |
4 | * by Alexander Schulz | |
5 | * | |
6 | * This file is used to get some basic information | |
7 | * about the memory layout of the shark we are running | |
8 | * on. Memory is usually divided in blocks a 8 MB. | |
9 | * And bootargs are copied from OpenFirmware. | |
10 | */ | |
11 | ||
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/types.h> | |
15 | #include <asm/setup.h> | |
16 | #include <asm/page.h> | |
17 | ||
18 | ||
19 | asmlinkage void | |
20 | create_params (unsigned long *buffer) | |
21 | { | |
22 | /* Is there a better address? Also change in mach-shark/core.c */ | |
23 | struct tag *tag = (struct tag *) 0x08003000; | |
24 | int j,i,m,k,nr_banks,size; | |
25 | unsigned char *c; | |
26 | ||
27 | k = 0; | |
28 | ||
29 | /* Head of the taglist */ | |
30 | tag->hdr.tag = ATAG_CORE; | |
31 | tag->hdr.size = tag_size(tag_core); | |
32 | tag->u.core.flags = 1; | |
33 | tag->u.core.pagesize = PAGE_SIZE; | |
34 | tag->u.core.rootdev = 0; | |
35 | ||
36 | /* Build up one tagged block for each memory region */ | |
37 | size=0; | |
38 | nr_banks=(unsigned int) buffer[0]; | |
39 | for (j=0;j<nr_banks;j++){ | |
40 | /* search the lowest address and put it into the next entry */ | |
41 | /* not a fast sort algorithm, but there are at most 8 entries */ | |
42 | /* and this is used only once anyway */ | |
43 | m=0xffffffff; | |
44 | for (i=0;i<(unsigned int) buffer[0];i++){ | |
45 | if (buffer[2*i+1]<m) { | |
46 | m=buffer[2*i+1]; | |
47 | k=i; | |
48 | } | |
49 | } | |
50 | ||
51 | tag = tag_next(tag); | |
52 | tag->hdr.tag = ATAG_MEM; | |
53 | tag->hdr.size = tag_size(tag_mem32); | |
54 | tag->u.mem.size = buffer[2*k+2]; | |
55 | tag->u.mem.start = buffer[2*k+1]; | |
56 | ||
57 | size += buffer[2*k+2]; | |
58 | ||
59 | buffer[2*k+1]=0xffffffff; /* mark as copied */ | |
60 | } | |
61 | ||
62 | /* The command line */ | |
63 | tag = tag_next(tag); | |
64 | tag->hdr.tag = ATAG_CMDLINE; | |
65 | ||
66 | c=(unsigned char *)(&buffer[34]); | |
67 | j=0; | |
68 | while (*c) tag->u.cmdline.cmdline[j++]=*c++; | |
69 | ||
70 | tag->u.cmdline.cmdline[j]=0; | |
71 | tag->hdr.size = (j + 7 + sizeof(struct tag_header)) >> 2; | |
72 | ||
73 | /* Hardware revision */ | |
74 | tag = tag_next(tag); | |
75 | tag->hdr.tag = ATAG_REVISION; | |
76 | tag->hdr.size = tag_size(tag_revision); | |
77 | tag->u.revision.rev = ((unsigned char) buffer[33])-'0'; | |
78 | ||
79 | /* End of the taglist */ | |
80 | tag = tag_next(tag); | |
81 | tag->hdr.tag = 0; | |
82 | tag->hdr.size = 0; | |
83 | } | |
84 | ||
85 | ||
86 | typedef int (*ofw_handle_t)(void *); | |
87 | ||
88 | /* Everything below is called with a wrong MMU setting. | |
89 | * This means: no string constants, no initialization of | |
90 | * arrays, no global variables! This is ugly but I didn't | |
91 | * want to write this in assembler :-) | |
92 | */ | |
93 | ||
94 | int | |
95 | of_decode_int(const unsigned char *p) | |
96 | { | |
97 | unsigned int i = *p++ << 8; | |
98 | i = (i + *p++) << 8; | |
99 | i = (i + *p++) << 8; | |
100 | return (i + *p); | |
101 | } | |
102 | ||
103 | int | |
104 | OF_finddevice(ofw_handle_t openfirmware, char *name) | |
105 | { | |
106 | unsigned int args[8]; | |
107 | char service[12]; | |
108 | ||
109 | service[0]='f'; | |
110 | service[1]='i'; | |
111 | service[2]='n'; | |
112 | service[3]='d'; | |
113 | service[4]='d'; | |
114 | service[5]='e'; | |
115 | service[6]='v'; | |
116 | service[7]='i'; | |
117 | service[8]='c'; | |
118 | service[9]='e'; | |
119 | service[10]='\0'; | |
120 | ||
121 | args[0]=(unsigned int)service; | |
122 | args[1]=1; | |
123 | args[2]=1; | |
124 | args[3]=(unsigned int)name; | |
125 | ||
126 | if (openfirmware(args) == -1) | |
127 | return -1; | |
128 | return args[4]; | |
129 | } | |
130 | ||
131 | int | |
132 | OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop) | |
133 | { | |
134 | unsigned int args[8]; | |
135 | char service[12]; | |
136 | ||
137 | service[0]='g'; | |
138 | service[1]='e'; | |
139 | service[2]='t'; | |
140 | service[3]='p'; | |
141 | service[4]='r'; | |
142 | service[5]='o'; | |
143 | service[6]='p'; | |
144 | service[7]='l'; | |
145 | service[8]='e'; | |
146 | service[9]='n'; | |
147 | service[10]='\0'; | |
148 | ||
149 | args[0] = (unsigned int)service; | |
150 | args[1] = 2; | |
151 | args[2] = 1; | |
152 | args[3] = (unsigned int)handle; | |
153 | args[4] = (unsigned int)prop; | |
154 | ||
155 | if (openfirmware(args) == -1) | |
156 | return -1; | |
157 | return args[5]; | |
158 | } | |
159 | ||
160 | int | |
161 | OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen) | |
162 | { | |
163 | unsigned int args[8]; | |
164 | char service[8]; | |
165 | ||
166 | service[0]='g'; | |
167 | service[1]='e'; | |
168 | service[2]='t'; | |
169 | service[3]='p'; | |
170 | service[4]='r'; | |
171 | service[5]='o'; | |
172 | service[6]='p'; | |
173 | service[7]='\0'; | |
174 | ||
175 | args[0] = (unsigned int)service; | |
176 | args[1] = 4; | |
177 | args[2] = 1; | |
178 | args[3] = (unsigned int)handle; | |
179 | args[4] = (unsigned int)prop; | |
180 | args[5] = (unsigned int)buf; | |
181 | args[6] = buflen; | |
182 | ||
183 | if (openfirmware(args) == -1) | |
184 | return -1; | |
185 | return args[7]; | |
186 | } | |
187 | ||
188 | asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) | |
189 | { | |
190 | int phandle,i,mem_len,buffer[32]; | |
191 | char temp[15]; | |
192 | ||
193 | temp[0]='/'; | |
194 | temp[1]='m'; | |
195 | temp[2]='e'; | |
196 | temp[3]='m'; | |
197 | temp[4]='o'; | |
198 | temp[5]='r'; | |
199 | temp[6]='y'; | |
200 | temp[7]='\0'; | |
201 | ||
202 | phandle=OF_finddevice(o,temp); | |
203 | ||
204 | temp[0]='r'; | |
205 | temp[1]='e'; | |
206 | temp[2]='g'; | |
207 | temp[3]='\0'; | |
208 | ||
209 | mem_len = OF_getproplen(o,phandle, temp); | |
210 | OF_getprop(o,phandle, temp, buffer, mem_len); | |
211 | *nomr=mem_len >> 3; | |
212 | ||
213 | for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]); | |
214 | ||
215 | temp[0]='/'; | |
216 | temp[1]='c'; | |
217 | temp[2]='h'; | |
218 | temp[3]='o'; | |
219 | temp[4]='s'; | |
220 | temp[5]='e'; | |
221 | temp[6]='n'; | |
222 | temp[7]='\0'; | |
223 | ||
224 | phandle=OF_finddevice(o,temp); | |
225 | ||
226 | temp[0]='b'; | |
227 | temp[1]='o'; | |
228 | temp[2]='o'; | |
229 | temp[3]='t'; | |
230 | temp[4]='a'; | |
231 | temp[5]='r'; | |
232 | temp[6]='g'; | |
233 | temp[7]='s'; | |
234 | temp[8]='\0'; | |
235 | ||
236 | mem_len = OF_getproplen(o,phandle, temp); | |
237 | OF_getprop(o,phandle, temp, buffer, mem_len); | |
238 | if (mem_len > 128) mem_len=128; | |
239 | for (i=0; i<=mem_len/4; i++) pointer[i+33]=buffer[i]; | |
240 | pointer[i+33]=0; | |
241 | ||
242 | temp[0]='/'; | |
243 | temp[1]='\0'; | |
244 | phandle=OF_finddevice(o,temp); | |
245 | temp[0]='b'; | |
246 | temp[1]='a'; | |
247 | temp[2]='n'; | |
248 | temp[3]='n'; | |
249 | temp[4]='e'; | |
250 | temp[5]='r'; | |
251 | temp[6]='-'; | |
252 | temp[7]='n'; | |
253 | temp[8]='a'; | |
254 | temp[9]='m'; | |
255 | temp[10]='e'; | |
256 | temp[11]='\0'; | |
257 | mem_len = OF_getproplen(o,phandle, temp); | |
258 | OF_getprop(o,phandle, temp, buffer, mem_len); | |
58dd48a6 | 259 | * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2]; |
1da177e4 | 260 | } |