block: add more diagnostic messages
[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 }