add support for module handling
[project/ubox.git] / board.c
1 /*
2 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License version 2.1
7 * as published by the Free Software Foundation
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21
22 #include <libubox/blobmsg_json.h>
23
24 #define CONFIG_FILE "/etc/boards.json"
25 #define MODEL_FILE "/proc/devicetree/model"
26 #define CPU_INFO "/proc/cpuinfo"
27
28 enum {
29 BOARD_ID,
30 __BOARD_MAX
31 };
32
33 static struct blob_buf b;
34
35 static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
36 [BOARD_ID] = { .name = "id", .type = BLOBMSG_TYPE_STRING },
37 };
38
39 static char* detect_mips_machine(void)
40 {
41 FILE *fp;
42 static char line[64];
43 char *ret = NULL;
44
45 fp = fopen(CPU_INFO, "r");
46 if (!fp) {
47 perror("fopen");
48 return NULL;
49 }
50
51 while (fgets(line, sizeof(line), fp)) {
52 if (!strncmp(line, "machine", 7)) {
53 char *machine = strstr(line, ": ");
54
55 if (!machine)
56 continue;
57
58 machine[strlen(machine) - 1] = '\0';
59
60 ret = &machine[2];
61 break;
62 }
63 }
64
65 fclose(fp);
66
67 return ret;
68 }
69
70 static char* detect_devicetree_model(void)
71 {
72 FILE *fp;
73 static char line[64];
74 char *ret = NULL;
75 struct stat s;
76
77 if (stat(MODEL_FILE, &s) || !S_ISREG(s.st_mode))
78 return NULL;
79
80 fp = fopen(MODEL_FILE, "r");
81 if (!fp) {
82 perror("fopen");
83 return NULL;
84 }
85
86 if (!fgets(line, sizeof(line), fp))
87 ret = line;
88
89 fclose(fp);
90
91 return ret;
92 }
93
94 static char* board_id(struct blob_attr *msg)
95 {
96 struct blob_attr *tb[__BOARD_MAX];
97
98 blobmsg_parse(board_policy, __BOARD_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
99 if (tb[BOARD_ID])
100 return blobmsg_data(tb[BOARD_ID]);
101
102 return NULL;
103 }
104
105 static void write_file(char *file, char *val)
106 {
107 FILE *fp;
108
109 fp = fopen(file, "w");
110 if (fp) {
111 fprintf(fp, val);
112 fclose(fp);
113 } else {
114 perror("fopen");
115 }
116
117 }
118
119 static int set_board(char *board, char *boardid)
120 {
121 if (!boardid) {
122 fprintf(stderr, "failed to detect board %s\n", board);
123 return -1;
124 }
125 printf("detected %s - %s\n", board, boardid);
126
127 mkdir("/tmp/sysinfo", 0755);
128
129 write_file("/tmp/sysinfo/model", board);
130 write_file("/tmp/sysinfo/board_name", boardid);
131
132 return 0;
133 }
134
135 static int load_json(char *file)
136 {
137 struct stat s;
138 int fd;
139 char *buf;
140
141 if (stat(file, &s) || !S_ISREG(s.st_mode)) {
142 fprintf(stderr, "failed to open %s\n", file);
143 return -1;
144 }
145
146 buf = malloc(s.st_size + 1);
147 if (!buf) {
148 perror("malloc");
149 return -1;
150 }
151
152 fd = open(file, O_RDONLY);
153 if (!fd) {
154 perror("open");
155 return -1;
156 }
157
158 if (read(fd, buf, s.st_size) != s.st_size) {
159 fprintf(stderr, "failed to read %s - %d bytes\n", file, (int)s.st_size);
160 close(fd);
161 return -1;
162 }
163 close(fd);
164 buf[s.st_size] = '\0';
165
166 blob_buf_init(&b, 0);
167 if (!blobmsg_add_json_from_string(&b, buf)) {
168 fprintf(stderr, "Failed to read json\n");
169 return - 1;
170 }
171 free(buf);
172
173 return 0;
174 }
175
176 int main(int argc, char **argv)
177 {
178 struct blob_attr *cur;
179 char *board;
180 int rem;
181
182 board = detect_mips_machine();
183 if (!board)
184 detect_devicetree_model();
185 if (!board) {
186 fprintf(stderr, "failed to detect board\n");
187 return -1;
188 }
189
190 if (load_json(CONFIG_FILE))
191 return -1;
192
193 blob_for_each_attr(cur, b.head, rem) {
194 if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE)
195 continue;
196 if (!strcmp(blobmsg_name(cur), board)) {
197 char *id = board_id(cur);
198
199 if (id)
200 return set_board(board, id);
201 }
202 }
203
204 fprintf(stderr, "failed to identify %s\n", board);
205
206 return -1;
207 }