Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/uboot/glue.c
34677 views
1
/*-
2
* Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <sys/types.h>
28
29
#include <zlib.h>
30
#include <stand.h>
31
#include "api_public.h"
32
#include "glue.h"
33
34
#ifdef DEBUG
35
#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
36
#else
37
#define debugf(fmt, args...)
38
#endif
39
40
/* Some random address used by U-Boot. */
41
extern long uboot_address;
42
43
static int
44
valid_sig(struct api_signature *sig)
45
{
46
uint32_t checksum;
47
struct api_signature s;
48
49
if (sig == NULL)
50
return (0);
51
/*
52
* Clear the checksum field (in the local copy) so as to calculate the
53
* CRC with the same initial contents as at the time when the sig was
54
* produced
55
*/
56
s = *sig;
57
s.checksum = crc32(0, Z_NULL, 0);
58
59
checksum = crc32(s.checksum, (void *)&s, sizeof(struct api_signature));
60
61
if (checksum != sig->checksum)
62
return (0);
63
64
return (1);
65
}
66
67
/*
68
* Checks to see if API signature's address was given to us as a command line
69
* argument by U-Boot.
70
*
71
* returns 1/0 depending on found/not found result
72
*/
73
int
74
api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig)
75
{
76
unsigned long api_address;
77
int c;
78
79
api_address = 0;
80
opterr = 0;
81
optreset = 1;
82
optind = 1;
83
84
while ((c = getopt (argc, argv, "a:")) != -1)
85
switch (c) {
86
case 'a':
87
api_address = strtoul(optarg, NULL, 16);
88
break;
89
default:
90
break;
91
}
92
93
if (api_address != 0) {
94
*sig = (struct api_signature *)api_address;
95
if (valid_sig(*sig))
96
return (1);
97
}
98
99
return (0);
100
}
101
102
/*
103
* Searches for the U-Boot API signature
104
*
105
* returns 1/0 depending on found/not found result
106
*/
107
int
108
api_search_sig(struct api_signature **sig)
109
{
110
unsigned char *sp, *spend;
111
112
if (sig == NULL)
113
return (0);
114
115
if (uboot_address == 0)
116
uboot_address = 255 * 1024 * 1024;
117
118
sp = (void *)(uboot_address & API_SIG_SEARCH_MASK);
119
spend = sp + API_SIG_SEARCH_LEN - API_SIG_MAGLEN;
120
121
while (sp < spend) {
122
if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
123
*sig = (struct api_signature *)sp;
124
if (valid_sig(*sig))
125
return (1);
126
}
127
sp += API_SIG_MAGLEN;
128
}
129
130
*sig = NULL;
131
return (0);
132
}
133
134
/****************************************
135
*
136
* console
137
*
138
****************************************/
139
140
int
141
ub_getc(void)
142
{
143
int c;
144
145
if (!syscall(API_GETC, NULL, &c))
146
return (-1);
147
148
return (c);
149
}
150
151
int
152
ub_tstc(void)
153
{
154
int t;
155
156
if (!syscall(API_TSTC, NULL, &t))
157
return (-1);
158
159
return (t);
160
}
161
162
void
163
ub_putc(const char c)
164
{
165
166
syscall(API_PUTC, NULL, &c);
167
}
168
169
void
170
ub_puts(const char *s)
171
{
172
173
syscall(API_PUTS, NULL, s);
174
}
175
176
/****************************************
177
*
178
* system
179
*
180
****************************************/
181
182
void
183
ub_reset(void)
184
{
185
186
syscall(API_RESET, NULL);
187
while (1); /* fallback if API_RESET failed */
188
__unreachable();
189
}
190
191
static struct mem_region mr[UB_MAX_MR];
192
static struct sys_info si;
193
194
struct sys_info *
195
ub_get_sys_info(void)
196
{
197
int err = 0;
198
199
memset(&si, 0, sizeof(struct sys_info));
200
si.mr = mr;
201
si.mr_no = UB_MAX_MR;
202
memset(&mr, 0, sizeof(mr));
203
204
if (!syscall(API_GET_SYS_INFO, &err, &si))
205
return (NULL);
206
207
return ((err) ? NULL : &si);
208
}
209
210
/****************************************
211
*
212
* timing
213
*
214
****************************************/
215
216
void
217
ub_udelay(unsigned long usec)
218
{
219
220
syscall(API_UDELAY, NULL, &usec);
221
}
222
223
unsigned long
224
ub_get_timer(unsigned long base)
225
{
226
unsigned long cur;
227
228
if (!syscall(API_GET_TIMER, NULL, &cur, &base))
229
return (0);
230
231
return (cur);
232
}
233
234
/****************************************************************************
235
*
236
* devices
237
*
238
* Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
239
*
240
***************************************************************************/
241
242
static struct device_info devices[UB_MAX_DEV];
243
244
struct device_info *
245
ub_dev_get(int i)
246
{
247
248
return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
249
}
250
251
/*
252
* Enumerates the devices: fills out device_info elements in the devices[]
253
* array.
254
*
255
* returns: number of devices found
256
*/
257
int
258
ub_dev_enum(void)
259
{
260
struct device_info *di;
261
int n = 0;
262
263
memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
264
di = &devices[0];
265
266
if (!syscall(API_DEV_ENUM, NULL, di))
267
return (0);
268
269
while (di->cookie != NULL) {
270
271
if (++n >= UB_MAX_DEV)
272
break;
273
274
/* take another device_info */
275
di++;
276
277
/* pass on the previous cookie */
278
di->cookie = devices[n - 1].cookie;
279
280
if (!syscall(API_DEV_ENUM, NULL, di))
281
return (0);
282
}
283
284
return (n);
285
}
286
287
/*
288
* handle: 0-based id of the device
289
*
290
* returns: 0 when OK, err otherwise
291
*/
292
int
293
ub_dev_open(int handle)
294
{
295
struct device_info *di;
296
int err = 0;
297
298
if (handle < 0 || handle >= UB_MAX_DEV)
299
return (API_EINVAL);
300
301
di = &devices[handle];
302
if (!syscall(API_DEV_OPEN, &err, di))
303
return (-1);
304
305
return (err);
306
}
307
308
int
309
ub_dev_close(int handle)
310
{
311
struct device_info *di;
312
313
if (handle < 0 || handle >= UB_MAX_DEV)
314
return (API_EINVAL);
315
316
di = &devices[handle];
317
if (!syscall(API_DEV_CLOSE, NULL, di))
318
return (-1);
319
320
return (0);
321
}
322
323
/*
324
* Validates device for read/write, it has to:
325
*
326
* - have sane handle
327
* - be opened
328
*
329
* returns: 0/1 accordingly
330
*/
331
static int
332
dev_valid(int handle)
333
{
334
335
if (handle < 0 || handle >= UB_MAX_DEV)
336
return (0);
337
338
if (devices[handle].state != DEV_STA_OPEN)
339
return (0);
340
341
return (1);
342
}
343
344
static int
345
dev_stor_valid(int handle)
346
{
347
348
if (!dev_valid(handle))
349
return (0);
350
351
if (!(devices[handle].type & DEV_TYP_STOR))
352
return (0);
353
354
return (1);
355
}
356
357
int
358
ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
359
lbasize_t *rlen)
360
{
361
struct device_info *di;
362
lbasize_t act_len;
363
int err = 0;
364
365
if (!dev_stor_valid(handle))
366
return (API_ENODEV);
367
368
di = &devices[handle];
369
if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
370
return (API_ESYSC);
371
372
if (!err && rlen)
373
*rlen = act_len;
374
375
return (err);
376
}
377
378
static int
379
dev_net_valid(int handle)
380
{
381
382
if (!dev_valid(handle))
383
return (0);
384
385
if (devices[handle].type != DEV_TYP_NET)
386
return (0);
387
388
return (1);
389
}
390
391
int
392
ub_dev_recv(int handle, void *buf, int len, int *rlen)
393
{
394
struct device_info *di;
395
int err = 0, act_len;
396
397
if (!dev_net_valid(handle))
398
return (API_ENODEV);
399
400
di = &devices[handle];
401
if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
402
return (API_ESYSC);
403
404
if (!err)
405
*rlen = act_len;
406
407
return (err);
408
}
409
410
int
411
ub_dev_send(int handle, void *buf, int len)
412
{
413
struct device_info *di;
414
int err = 0;
415
416
if (!dev_net_valid(handle))
417
return (API_ENODEV);
418
419
di = &devices[handle];
420
if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
421
return (API_ESYSC);
422
423
return (err);
424
}
425
426
char *
427
ub_stor_type(int type)
428
{
429
430
if (type & DT_STOR_IDE)
431
return ("IDE");
432
433
if (type & DT_STOR_SCSI)
434
return ("SCSI");
435
436
if (type & DT_STOR_USB)
437
return ("USB");
438
439
if (type & DT_STOR_MMC)
440
return ("MMC");
441
442
if (type & DT_STOR_SATA)
443
return ("SATA");
444
445
return ("Unknown");
446
}
447
448
char *
449
ub_mem_type(int flags)
450
{
451
452
switch (flags & 0x000F) {
453
case MR_ATTR_FLASH:
454
return ("FLASH");
455
case MR_ATTR_DRAM:
456
return ("DRAM");
457
case MR_ATTR_SRAM:
458
return ("SRAM");
459
default:
460
return ("Unknown");
461
}
462
}
463
464
void
465
ub_dump_di(int handle)
466
{
467
struct device_info *di = ub_dev_get(handle);
468
int i;
469
470
printf("device info (%d):\n", handle);
471
printf(" cookie\t= %p\n", di->cookie);
472
printf(" type\t\t= 0x%08x\n", di->type);
473
474
if (di->type == DEV_TYP_NET) {
475
printf(" hwaddr\t= ");
476
for (i = 0; i < 6; i++)
477
printf("%02x ", di->di_net.hwaddr[i]);
478
479
printf("\n");
480
481
} else if (di->type & DEV_TYP_STOR) {
482
printf(" type\t\t= %s\n", ub_stor_type(di->type));
483
printf(" blk size\t\t= %ld\n", di->di_stor.block_size);
484
printf(" blk count\t\t= %ld\n", di->di_stor.block_count);
485
}
486
}
487
488
void
489
ub_dump_si(struct sys_info *si)
490
{
491
int i;
492
493
printf("sys info:\n");
494
printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000);
495
printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000);
496
printf(" bar\t\t= 0x%08lx\n", si->bar);
497
498
printf("---\n");
499
for (i = 0; i < si->mr_no; i++) {
500
if (si->mr[i].flags == 0)
501
break;
502
503
printf(" start\t= 0x%08lx\n", si->mr[i].start);
504
printf(" size\t= 0x%08lx\n", si->mr[i].size);
505
printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags));
506
printf("---\n");
507
}
508
}
509
510
/****************************************
511
*
512
* env vars
513
*
514
****************************************/
515
516
char *
517
ub_env_get(const char *name)
518
{
519
char *value;
520
521
if (!syscall(API_ENV_GET, NULL, name, &value))
522
return (NULL);
523
524
return (value);
525
}
526
527
void
528
ub_env_set(const char *name, char *value)
529
{
530
531
syscall(API_ENV_SET, NULL, name, value);
532
}
533
534
static char env_name[256];
535
536
const char *
537
ub_env_enum(const char *last)
538
{
539
const char *env, *str;
540
int i;
541
542
/*
543
* It's OK to pass only the name piece as last (and not the whole
544
* 'name=val' string), since the API_ENUM_ENV call uses envmatch()
545
* internally, which handles such case
546
*/
547
env = NULL;
548
if (!syscall(API_ENV_ENUM, NULL, last, &env))
549
return (NULL);
550
551
if (env == NULL || last == env)
552
/* no more env. variables to enumerate */
553
return (NULL);
554
555
/* next enumerated env var */
556
memset(env_name, 0, 256);
557
for (i = 0, str = env; *str != '=' && *str != '\0';)
558
env_name[i++] = *str++;
559
560
env_name[i] = '\0';
561
562
return (env_name);
563
}
564
565