1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*
* Copyright (C) 2015 Juergen Borleis <kernel@pengutronix.de>
*
* Based on code from:
* Copyright (C) 2013 Jan Luebbe <j.luebbe@pengutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <common.h>
#include <errno.h>
#include <fcntl.h>
#include <fs.h>
#include <globalvar.h>
#include <xfuncs.h>
#include <init.h>
#include <net.h>
#define PCM030_EEPROM_DEVICE "/dev/eeprom0"
/*
* The first 2048 bytes contain the U-Boot environment shipped with the boards.
* After that an area begins where some board specific and partially unique data
* is stored. All of this data is plain test, string delimiter is the semicolon.
* the last string terminates with a '\0'.
* One example found in the 'product' area: PCM-030-02REI;017822;0050C2875974\0
* The first string seems to be the product type, the second string some kind
* of serial number and the last string the boards unique MAC.
*/
struct pcm030_eeprom {
char env[0x800]; /* u-boot environment */
char product[0x80]; /* <product>;<serno>;<mac>\0 */
} __attribute__((packed));
static void pcm030_read_factory_data(const struct pcm030_eeprom *buf)
{
unsigned u, l;
char *board, *serial;
char *full_mac = "xx:xx:xx:xx:xx:xx";
u8 enetaddr[6];
u = 0;
for (l = 0; (l + u) < sizeof(buf->product); l++) {
if (buf->product[u + l] != ';')
continue;
board = xstrndup(&buf->product[u], l);
u += l + 1;
globalvar_add_simple_string_fixed("model.type", board);
free(board);
}
for (l = 0; (l + u) < sizeof(buf->product); l++) {
if (buf->product[u + l] != ';')
continue;
serial = xstrndup(&buf->product[u], l);
u += l + 1;
globalvar_add_simple_string_fixed("model.serial", serial);
free(serial);
}
/* for the MAC do a simple duck test */
if (buf->product[u] != ';' && buf->product[u + 12] == '\0') {
full_mac[0] = buf->product[u + 0];
full_mac[1] = buf->product[u + 1];
full_mac[3] = buf->product[u + 2];
full_mac[4] = buf->product[u + 3];
full_mac[6] = buf->product[u + 4];
full_mac[7] = buf->product[u + 5];
full_mac[9] = buf->product[u + 6];
full_mac[10] = buf->product[u + 7];
full_mac[12] = buf->product[u + 8];
full_mac[13] = buf->product[u + 9];
full_mac[15] = buf->product[u + 10];
full_mac[16] = buf->product[u + 11];
string_to_ethaddr(full_mac, enetaddr);
eth_register_ethaddr(0, enetaddr);
return;
}
printf("EEPROM contains no ethernet MAC\n");
}
static int pcm030_eeprom_read(void)
{
int fd, ret;
struct pcm030_eeprom *buf;
fd = open(PCM030_EEPROM_DEVICE, O_RDONLY);
if (fd < 0) {
perror("failed to open " PCM030_EEPROM_DEVICE);
return fd;
}
buf = xmalloc(sizeof(struct pcm030_eeprom));
ret = pread(fd, buf, sizeof(struct pcm030_eeprom), 0);
if (ret < sizeof(struct pcm030_eeprom)) {
perror("failed to read " PCM030_EEPROM_DEVICE);
goto out;
}
pcm030_read_factory_data(buf);
ret = 0;
out:
free(buf);
close(fd);
return ret;
}
late_initcall(pcm030_eeprom_read);
|