1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2012 Daniil Lunev
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/types.h>
20 #include <grub/emu/misc.h>
21 #include <grub/emu/getroot.h>
22 #include <grub/fs.h>
23 #include <grub/device.h>
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #define BUFFER_SIZE 512
30
31 struct commands {
32 const char * lst;
33 const char * cfg;
34 };
35
36 void
37 get_uuid_by_path(char * path, char ** uuid)
38 {
39 char ** devices = NULL;
40 char * drive = NULL;
41 grub_device_t dev = NULL;
42 grub_fs_t fs = NULL;
43 char * grub_path = NULL;
44
45 grub_path = canonicalize_file_name(path);
46 if (! grub_path)
47 grub_util_error("Can't canonicalize path");
48
49 devices = grub_guess_root_devices(grub_path);
50 if (! devices)
51 grub_util_error("Can't find device");
52
53 drive = grub_util_get_grub_dev(devices[0]);
54 if (! drive)
55 grub_util_error("Can't get drive");
56
57 dev = grub_device_open(drive);
58 if (! dev)
59 grub_util_error("Can't open device");
60
61 fs = grub_fs_probe(dev);
62 if (! fs)
63 grub_util_error("Probing fs error");
64
65 if (! fs->uuid)
66 grub_util_error("This fs doesn't support uuid");
67
68 if (fs->uuid(dev, uuid) != GRUB_ERR_NONE)
69 grub_util_error("%s", grub_errmsg);
70
71 free(grub_path);
72 if (dev)
73 grub_device_close(dev);
74
75 return;
76 }
77
78 struct commands com[] = {
79 {"title", "entry_name"},
80 {"findroot", "pool"},
81 {"bootfs", "data_set"},
82 {"kernel$", "kernel_path"},
83 {"module$", "module"},
84 {"default", "default_entry"},
85 {"timeout", "timeout"},
86 {"serial", "serial"},
87 {"terminal", "terminal"},
88 {0, 0},
89 };
90
91 int
92 get_command_id(char * command)
93 {
94 int i = 0;
95 for (; com[i].lst; ++i)
96 if (!strcmp(com[i].lst, command))
97 return i;
98 return -1;
99 }
100
101 char *
102 retrive_value(char * val)
103 {
104 char * str;
105 int quote_flag = 0;;
106
107 while ((*val == ' ') || (*val == '\t'))
108 ++val;
109
110 if (*val == '"') {
111 ++val;
112 ++quote_flag;
113 }
114
115 str = val;
116
117 for (;;) {
118 if (quote_flag) {
119 if (*val == '"')
120 break;
121 if (*val == '\0')
122 return NULL;
123 } else {
124 if ((*val == ' ') || (*val == '\t') || (*val == '\0'))
125 break;
126 }
127 ++val;
128 }
129 *val = '\0';
130
131 return str;
132 }
133
134 int
135 parse_menulst(FILE * in_file, FILE * out_file)
136 {
137 char line[BUFFER_SIZE];
138 char * command;
139 char * value;
140 char * label = NULL;
141 char bootfs[BUFFER_SIZE];
142 char pool[BUFFER_SIZE];
143 char * uuid;
144 char * c;
145 int com_id;
146
147 for (;;) {
148 command = fgets(line, BUFFER_SIZE, in_file);
149 if (! command)
150 return 0;
151
152 c = command + strlen(command) - 1;
153 if ((*c != '\n') && (fgets(line, BUFFER_SIZE, in_file)))
154 return 1;
155
156 if ((*command == '#') || (*command == ' ')
157 || (*command == '\t') || (*command == '\n'))
158 continue;
159
160 if (*c == '\n')
161 *c = '\0';
162 value = strchr(line, ' ');
163 if (! value)
164 continue;
165
166 *value++ = '\0';
167
168 com_id = get_command_id(command);
169 if (com_id < 0)
170 continue;
171
172 switch (com_id) {
173 case 0:
174 fprintf(out_file,"\n%s=%s\n", com[com_id].cfg, value);
175 break;
176 case 1:
177 label = strdup(strchr(value, '_') + 1);
178 c = strchr(label, ',');
179 if (c)
180 *c = 0;
181 continue;
182 case 2:
183 c = strchr(value, '/');
184 if (c != NULL) {
185 strcpy(bootfs, c);
186 *c = '\0';
187 strcpy(pool + 1, value);
188 *pool = '/';
189 uuid = NULL;
190 get_uuid_by_path(pool, &uuid);
191 if (! uuid)
192 return 1;
193
194 fprintf(out_file,"pool_uuid=%s\n", uuid);
195
196 }
197 *c = '/';
198 fprintf(out_file,"data_set=%s\n", value);
199 if (label) {
200 free(label);
201 label = NULL;
202 }
203 break;
204 case 3:
205 case 4:
206 if (label) {
207 fprintf(out_file,"pool_label=%s\n", label);
208 free(label);
209 label = NULL;
210 }
211 if (com_id == 3)
212 c = strchr (value, ' ');
213 if (c)
214 *c = '\0';
215 if (! value)
216 return 1;
217
218 fprintf(out_file,"%s=%s\n", com[com_id].cfg, value);
219
220 if ((com_id == 3) && (c)) {
221 char * tmp;
222 value = c + 1;
223 tmp = strstr(value, "ZFS-BOOTFS");
224 if (tmp)
225 *(tmp + 3) = '_';
226 fprintf(out_file,"kernel_options=%s\n", value);
227 }
228
229 break;
230 default:
231 fprintf(out_file,"%s=%s\n", com[com_id].cfg, value);
232 break;
233 }
234 }
235 return 0;
236 }
237
238 int
239 main(int argc, char ** argv)
240 {
241 FILE * lst_file;
242 FILE * cfg_file;
243 int err = 0;
244
245 if (argc != 3) {
246 printf("grub-solarislst2cfg lst_file cfg_file\n");
247 return 1;
248 }
249
250 lst_file = fopen(argv[1], "r");
251 if (! lst_file)
252 return 1;
253
254 cfg_file = fopen(argv[2], "w");
255 if (! cfg_file) {
256 fclose(lst_file);
257 return 1;
258 }
259
260 grub_util_init_nls();
261 grub_util_biosdisk_init(DEFAULT_DEVICE_MAP);
262 grub_init_all();
263
264 err = parse_menulst(lst_file, cfg_file);
265
266 grub_fini_all();
267
268 fclose(lst_file);
269 fclose(cfg_file);
270
271 if (err)
272 remove(argv[2]);
273 return err;
274 }