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 }