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 }