OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / fconfig / fconfig.c
1 /*
2  * fconfig.c
3  *
4  * $Id: fconfig.c,v 1.1 2006/02/13 09:58:08 andrzej Exp $
5  *
6  * Redboot Flash Configuration parser. 
7  * Main file. 
8  *
9  * Copyright (C) 2006 Ekiert sp z o.o.
10  * Author: Andrzej Ekiert <a.ekiert@ekiert.com>
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version
15  * 2 of the License, or (at your option) any later version. 
16  *
17  * Usage hints:
18  * The 'device' is probably going to be an MTD device. You may also operate
19  * on an ordinary file. However, if you're working with MTD, it's highly 
20  * recommended to open it as a character device, not as a block device 
21  * (eg. open /dev/mtd[n], not /dev/mtdblock[n]). If an MTD device is emulating
22  * a block device, then the OS will do heavy caching (a lot of unneccessary 
23  * reads), and will do block writes, while in character device mode it's
24  * possible to actually write exactly these bytes, that have been changed
25  * (see my 24xx I2C EEPROM driver - ee24.c). In case of operation with slow
26  * I2C EEPROMs this allows to speed up things and to save on EEPROM wear-out. 
27  *
28  * The above should explain why mmap() is not used in this application ;-)
29  * (initially it was, but the performance was poor, when we're forced to work
30  *  with slow block devices). 
31  */
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38
39 #include "debug.h"
40 #include "ftypes.h"
41 #include "crunchfc.h"
42
43 /*
44  * Parse type name, return type ID. 
45  * Type ID is the type number in the type table. 
46  */
47 /*
48 static int8_t parse_type(uint8_t *type)
49 {
50         uint8_t i, ret = -1;
51
52         MESSAGE(VERB_HIGH, "Parsing type: %s\n", type);
53         for (i = 0; i < NUM_TYPES; i++) {
54                 if (strncmp(TYPE_NAME(i), type, MAX_TYPE_NAME)==0) {
55                         MESSAGE(VERB_HIGH, "Found type: ID = %d\n", i);
56                         ret = i;
57                         break;
58                 }
59         }
60         return ret;
61 }
62 */
63
64 /*
65  * Print usage information.
66  */
67 static void usage(void)
68 {
69         uint8_t i;
70         if (verbosity == 0) {
71                 return;
72         }
73
74         fputs("Read or write Redboot configuration\n", stdout);
75         fputs("usage: fconfig [-r|-w] -d dev -n nickname -x value\n", stdout);
76         fputs("'dev' may be a char device, block device or a file\n", stdout);
77         fputs("Supported types: \n", stdout);
78         for (i = 0; i < NUM_TYPES; i++) {
79                 printf(" - %s\n", TYPE_NAME(i));
80         }
81         fputs("Additional switches: \n", stdout);
82         fputs(" -v:\tVerbose mode, use more to increase verbosity\n", stdout);
83         fputs(" -s:\tSilent mode, absolutely no messages printed\n", stdout);
84 }
85
86 /*
87  * Open the file or device containing configuration and copy the configuration 
88  * data to a buffer. We could mmap() here and operate directly on mmaped data 
89  * (it'd make life easier later), but that would force us to work with MTD in 
90  * block device emulation mode (see comments at the top of this file). 
91  *
92  * Remember, that the MTD partition is likely to be "forced read-only", 
93  * if the partition size is not equal to erase block size.
94  */
95 static uint8_t buffer[MAX_CONFIG_DATA];
96 struct config_data *get_fconfig_handle(struct config_data *data, 
97         uint8_t *dev, mode_t mode)
98 {
99         uint16_t count;
100
101         if ((data->fd = open(dev, mode)) < 0) {
102                 MESSAGE(VERB_LOW, "Failed to open device or file %s!\n", dev);
103                 return NULL;
104         }
105         
106         count = read(data->fd, buffer, MAX_CONFIG_DATA);
107         if (count <= 0) {
108                 MESSAGE(VERB_LOW, "Nothing read!\n");
109                 close(data->fd);
110                 return NULL;
111         }
112         MESSAGE(VERB_NORMAL, "Read %d bytes\n", count);
113
114         data->buf = buffer;
115         data->maxlen = count;
116         return data;
117 }
118
119 /*
120  * Synchronize the data back and close the file or device containing 
121  * the configuration data. 
122  */
123 void close_fconfig_handle(struct config_data *data)
124 {
125         close(data->fd);
126 }
127
128 /*
129  * Write mode of operation: set parameter values in the configuration. 
130  */
131 static int write_mode(struct config_data *data, uint8_t *device, 
132         uint8_t *nickname, uint8_t *value)
133 {
134         if (value == NULL) {
135                 MESSAGE(VERB_LOW, "You must provide a value in WRITE mode\n");
136                 return 1;
137         }
138
139         if (get_fconfig_handle(data, device, O_RDWR) == NULL) {
140                 MESSAGE(VERB_LOW, "Could not get a config data handle!\n");
141                 return 1;
142         }
143         if (verify_fconfig(data)) {
144                 MESSAGE(VERB_LOW, "Config verification failed!\n");
145                 goto exit_fail;
146         }
147
148         if (set_key_value(data, nickname, value)) {
149                 goto exit_fail;
150         }
151
152         recalculate_crc(data);
153
154         close_fconfig_handle(data);
155         return 0;
156
157 exit_fail: 
158         close_fconfig_handle(data);
159         return 1;
160 }
161
162 /*
163  * Read mode of operation: get parameter values from the configuration. 
164  */
165 static int read_mode(struct config_data *data, uint8_t *device, 
166         uint8_t *nickname)
167 {
168         if (get_fconfig_handle(data, device, O_RDONLY) == NULL) {
169                 MESSAGE(VERB_LOW, "Could not get a config data handle!\n");
170                 return 1;
171         }
172         if (verify_fconfig(data)) {
173                 MESSAGE(VERB_LOW, "Config verification failed!\n");
174                 goto exit_fail;
175         }
176
177         if (get_key_value(data, nickname)) {
178                 goto exit_fail;
179         }
180
181         close_fconfig_handle(data);
182         return 0;
183
184 exit_fail: 
185         close_fconfig_handle(data);
186         return 1;
187 }
188
189 #define MODE_NONE 0
190 #define MODE_WRITE 1
191 #define MODE_READ 2
192
193 /*
194  * main(). ...nuff said.
195  */
196 int main(int argc, char **argv)
197 {
198         struct config_data data;
199         int c, ret;
200         uint8_t mode = MODE_NONE;
201         uint8_t *nickname = NULL;
202         uint8_t *value = NULL;
203         uint8_t *device = NULL;
204
205         while ((c = getopt(argc, argv, "hrwvsd:n:x:")) != -1) {
206                 switch (c) {
207                 case 'r':
208                         mode = MODE_READ;
209                         break;
210                 case 'w': 
211                         mode = MODE_WRITE;
212                         break;
213                 case 'n':
214                         nickname = optarg;
215                         break;
216                 case 'x':
217                         value = optarg;
218                         break;
219                 case 'v':
220                         verbosity++;
221                         break;
222                 case 's':
223                         verbosity = 0;
224                         break;
225                 case 'd':
226                         device = optarg;
227                         break;
228                 case 'h':
229                         usage();
230                         break;
231                 case '?':
232                 default:
233                         usage();
234                         exit(1);
235                         break;
236                 }
237         }
238
239         MESSAGE(VERB_LOW, "Low verbosity messages are printed.\n");
240         MESSAGE(VERB_NORMAL, "Normal verbosity messages are printed.\n");
241         MESSAGE(VERB_HIGH, "High verbosity messages are printed.\n");
242
243         if (nickname == NULL) {
244                 usage();
245                 exit(1);
246         }
247
248         if (device == NULL) {
249                 MESSAGE(VERB_LOW, "You must provide a device name.\n");
250                 exit(1);
251         }
252
253         switch (mode) {
254                 case MODE_WRITE : 
255                         ret = write_mode(&data, device, nickname, value);
256                         break;
257                 case MODE_READ : 
258                         ret = read_mode(&data, device, nickname);
259                         break;
260                 default : 
261                         MESSAGE(VERB_LOW, "Unknown mode of operation\n");
262                         usage();
263                         ret = 1;
264         } //switch
265
266         return ret;
267 }
268