File: /usr/src/linux/arch/arm/boot/compressed/ofw-shark.c

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