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 #define VALUE_SIZE 512 20 21 typedef struct entries entries; 22 struct entries { 23 entries *next; 24 char ** entry_info; 25 }; 26 27 enum param_consts { 28 ENTRY_NAME, 29 POOL_UUID, 30 POOL_LABEL, 31 DATA_SET, 32 KERNEL_PATH, 33 KERNEL_OPTIONS, 34 BA_PATH, 35 DOLLAR_KERNEL_PATH, 36 DOLLAR_BA_PATH, 37 }; 38 39 static const char * params_list[] = { 40 "entry_name", 41 "pool_uuid", 42 "pool_label", 43 "data_set", 44 "kernel_path", 45 "kernel_options", 46 "module", 47 "kernel_path$", 48 "module$", 49 NULL 50 }; 51 52 static grub_err_t 53 init_entries(entries ** menu_entries) 54 { 55 (*menu_entries) = (entries*) grub_zalloc(sizeof (menu_entries)); 56 if (! *menu_entries) 57 return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated")); 58 return 0; 59 } 60 61 static entries * 62 new_entry(char * name, entries * entry_list) 63 { 64 unsigned int i; 65 66 if (entry_list->next) 67 do { 68 entry_list = entry_list->next; 69 if (!grub_strcmp(name, entry_list->entry_info[0])) 70 return entry_list; 71 } while (entry_list->next); 72 entry_list->next = (entries*) grub_zalloc(sizeof(entries)); 73 if (! entry_list->next) 74 return NULL; 75 entry_list = entry_list->next; 76 entry_list->entry_info = (char**) grub_zalloc(sizeof(params_list)); 77 for (i = 0; i < sizeof(params_list) / sizeof(*params_list); i++) { 78 entry_list->entry_info[i] = (char *) grub_zalloc(VALUE_SIZE); 79 if (! entry_list->entry_info[i]) 80 return NULL; 81 } 82 grub_strcpy(entry_list->entry_info[0], name); 83 return entry_list; 84 } 85 86 static void 87 clear_entries(entries * entry_list) 88 { 89 entries * next; 90 unsigned int i; 91 92 next = entry_list->next; 93 grub_free(entry_list); 94 entry_list = next; 95 96 while (entry_list) { 97 next = entry_list->next; 98 if (entry_list->entry_info) { 99 for (i = 0; i < sizeof(params_list) / sizeof(*params_list); i++) 100 if (entry_list->entry_info[i]) 101 grub_free(entry_list->entry_info[i]); 102 grub_free(entry_list->entry_info); 103 } 104 grub_free(entry_list); 105 entry_list = next; 106 } 107 } 108 109 static grub_err_t 110 add_entries(entries * menu_entries) 111 { 112 grub_err_t err; 113 char cl1[] = "os"; 114 char cl2[] = "illumos"; 115 char * class[] = {cl1, cl2, NULL}; 116 char * argv[] = { NULL, NULL }; 117 char id[512]; 118 char * entry_source = NULL; 119 char * data_set; 120 char entry_template[] = 121 "insmod part_sunpc\n" 122 "insmod part_msdos\n" 123 "insmod zfs\n" 124 "insmod gzio\n" 125 "if cpuid -l ; then\n" 126 " ISADIR=amd64\n" 127 "else\n" 128 " ISADIR=\n" 129 "fi\n"; 130 131 menu_entries = menu_entries->next; 132 while (menu_entries) { 133 argv[0] = grub_strdup(menu_entries->entry_info[ENTRY_NAME]); 134 if (!argv[0]) 135 return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated")); 136 entry_source = (char*) grub_zalloc(2048); 137 138 if (!entry_source) 139 return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("memory can not be allocated")); 140 141 if (menu_entries->entry_info[DATA_SET][0] != 0) 142 data_set = grub_strchr(menu_entries->entry_info[DATA_SET], '/'); 143 else 144 data_set = grub_strdup("$ZFS_DATASET"); 145 grub_strcpy(entry_source, entry_template); 146 if (menu_entries->entry_info[POOL_UUID][0]) { 147 grub_strcat(entry_source, "search --no-floppy --zfs-mirror --fs-uuid --set=root "); 148 grub_strcat(entry_source, menu_entries->entry_info[POOL_UUID]); 149 } else { 150 grub_strcat(entry_source, "search --no-floppy --zfs-mirror --label --set=root "); 151 grub_strcat(entry_source, menu_entries->entry_info[POOL_LABEL]); 152 } 153 grub_strcat(entry_source, "\n"); 154 grub_strcat(entry_source, "zfs-bootfs ($root)"); 155 if (menu_entries->entry_info[DATA_SET][0] != 0) { 156 grub_strcat(entry_source, data_set); 157 grub_strcat(entry_source, " ZFS_BOOTFS\n"); 158 } else { 159 grub_strcat(entry_source, "default ZFS_BOOTFS ZFS_DATASET\n"); 160 } 161 grub_strcat(entry_source, "multiboot ($root)"); 162 if (! menu_entries->entry_info[DOLLAR_KERNEL_PATH][0]) { 163 grub_strcat(entry_source, data_set); 164 grub_strcat(entry_source, "/@"); 165 grub_strcat(entry_source, menu_entries->entry_info[KERNEL_PATH]); 166 grub_strcat(entry_source, " "); 167 grub_strcat(entry_source, menu_entries->entry_info[KERNEL_PATH]); 168 } else { 169 grub_strcat(entry_source, menu_entries->entry_info[DOLLAR_KERNEL_PATH]); 170 } 171 grub_strcat(entry_source, " "); 172 grub_strcat(entry_source, menu_entries->entry_info[KERNEL_OPTIONS]); 173 grub_strcat(entry_source, "\n"); 174 grub_strcat(entry_source, "module ($root)"); 175 if (! menu_entries->entry_info[DOLLAR_KERNEL_PATH][0]) { 176 grub_strcat(entry_source, data_set); 177 grub_strcat(entry_source, "/@"); 178 grub_strcat(entry_source, menu_entries->entry_info[BA_PATH]); 179 grub_strcat(entry_source, " "); 180 grub_strcat(entry_source, menu_entries->entry_info[BA_PATH]); 181 } else { 182 grub_strcat(entry_source, menu_entries->entry_info[DOLLAR_BA_PATH]); 183 } 184 185 grub_strcpy(id, argv[0]); 186 grub_strcat(id, "-"); 187 grub_strcat(id, menu_entries->entry_info[POOL_UUID]); 188 189 err = grub_normal_add_menu_entry (2, (const char **) argv, class, id, 190 NULL, NULL, NULL, entry_source, 0); 191 192 if (err) 193 return err; 194 195 grub_free(argv[0]); 196 menu_entries = menu_entries->next; 197 } 198 grub_free(entry_source); 199 return 0; 200 }