Lines 22-27
Link Here
|
22 |
|
22 |
|
23 |
grub_jmp_buf restart_env; |
23 |
grub_jmp_buf restart_env; |
24 |
|
24 |
|
|
|
25 |
gfx_data_t *graphics_data; |
26 |
|
25 |
#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) |
27 |
#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS) |
26 |
|
28 |
|
27 |
# if defined(PRESET_MENU_STRING) |
29 |
# if defined(PRESET_MENU_STRING) |
Lines 234-239
run_menu (char *menu_entries, char *config_entries, int num_entries,
Link Here
|
234 |
int c, time1, time2 = -1, first_entry = 0; |
236 |
int c, time1, time2 = -1, first_entry = 0; |
235 |
char *cur_entry = 0; |
237 |
char *cur_entry = 0; |
236 |
|
238 |
|
|
|
239 |
cls(); |
240 |
|
237 |
/* |
241 |
/* |
238 |
* Main loop for menu UI. |
242 |
* Main loop for menu UI. |
239 |
*/ |
243 |
*/ |
Lines 261-274
restart:
Link Here
|
261 |
/* Get current time. */ |
265 |
/* Get current time. */ |
262 |
while ((time1 = getrtsecs ()) == 0xFF) |
266 |
while ((time1 = getrtsecs ()) == 0xFF) |
263 |
; |
267 |
; |
|
|
268 |
grub_printf("\rPress any key to enter the menu\n\n\n"); |
264 |
|
269 |
|
265 |
while (1) |
270 |
while (1) |
266 |
{ |
271 |
{ |
267 |
/* Check if ESC is pressed. */ |
272 |
/* Check if ESC is pressed. */ |
268 |
if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e') |
273 |
if (checkkey () != -1) |
269 |
{ |
274 |
{ |
270 |
grub_timeout = -1; |
275 |
grub_timeout = -1; |
271 |
show_menu = 1; |
276 |
show_menu = 1; |
|
|
277 |
getkey (); |
272 |
break; |
278 |
break; |
273 |
} |
279 |
} |
274 |
|
280 |
|
Lines 287-293
restart:
Link Here
|
287 |
grub_timeout--; |
293 |
grub_timeout--; |
288 |
|
294 |
|
289 |
/* Print a message. */ |
295 |
/* Print a message. */ |
290 |
grub_printf ("\rPress `ESC' to enter the menu... %d ", |
296 |
grub_printf ("\rBooting %s in %d seconds...", |
|
|
297 |
get_entry(menu_entries, first_entry + entryno, 0), |
291 |
grub_timeout); |
298 |
grub_timeout); |
292 |
} |
299 |
} |
293 |
} |
300 |
} |
Lines 310-315
restart:
Link Here
|
310 |
|
317 |
|
311 |
if (! auth && password) |
318 |
if (! auth && password) |
312 |
{ |
319 |
{ |
|
|
320 |
if (*graphics_file) |
321 |
{ |
322 |
printf ("\ |
323 |
WARNING: graphical menu doesn\'t work\ |
324 |
in conjunction with the password feature\n" ); |
325 |
} |
313 |
printf ("\ |
326 |
printf ("\ |
314 |
Press enter to boot the selected OS or \'p\' to enter a\n\ |
327 |
Press enter to boot the selected OS or \'p\' to enter a\n\ |
315 |
password to unlock the next set of features."); |
328 |
password to unlock the next set of features."); |
Lines 319-325
restart:
Link Here
|
319 |
if (config_entries) |
332 |
if (config_entries) |
320 |
printf ("\ |
333 |
printf ("\ |
321 |
Press enter to boot the selected OS, \'e\' to edit the\n\ |
334 |
Press enter to boot the selected OS, \'e\' to edit the\n\ |
322 |
commands before booting, or \'c\' for a command-line."); |
335 |
commands before booting, \'a\' to modify the kernel arguments\n\ |
|
|
336 |
before booting, or \'c\' for a command-line."); |
323 |
else |
337 |
else |
324 |
printf ("\ |
338 |
printf ("\ |
325 |
Press \'b\' to boot, \'e\' to edit the selected command in the\n\ |
339 |
Press \'b\' to boot, \'e\' to edit the selected command in the\n\ |
Lines 697-702
restart:
Link Here
|
697 |
enter_cmdline (heap, 0); |
711 |
enter_cmdline (heap, 0); |
698 |
goto restart; |
712 |
goto restart; |
699 |
} |
713 |
} |
|
|
714 |
if (config_entries && c == 'a') |
715 |
{ |
716 |
int new_num_entries = 0, i = 0, j; |
717 |
char *new_heap; |
718 |
char * entries; |
719 |
char * entry_copy; |
720 |
char * append_line; |
721 |
char * start; |
722 |
|
723 |
entry_copy = new_heap = heap; |
724 |
cur_entry = get_entry (config_entries, first_entry + entryno, |
725 |
1); |
726 |
|
727 |
do |
728 |
{ |
729 |
while ((*(new_heap++) = cur_entry[i++]) != 0); |
730 |
new_num_entries++; |
731 |
} |
732 |
while (config_entries && cur_entry[i]); |
733 |
|
734 |
/* this only needs to be done if config_entries is non-NULL, |
735 |
but it doesn't hurt to do it always */ |
736 |
*(new_heap++) = 0; |
737 |
|
738 |
new_heap = heap + NEW_HEAPSIZE + 1; |
739 |
|
740 |
entries = entry_copy; |
741 |
while (*entries) |
742 |
{ |
743 |
if ((strstr(entries, "kernel") == entries) && |
744 |
isspace(entries[6])) |
745 |
break; |
746 |
|
747 |
while (*entries) entries++; |
748 |
entries++; |
749 |
} |
750 |
|
751 |
if (!*entries) |
752 |
goto restart; |
753 |
|
754 |
start = entries + 6; |
755 |
|
756 |
/* skip the white space */ |
757 |
while (*start && isspace(*start)) start++; |
758 |
/* skip the kernel name */ |
759 |
while (*start && !isspace(*start)) start++; |
760 |
/* skip the white space */ |
761 |
while (*start && isspace(*start)) start++; |
762 |
|
763 |
append_line = new_heap; |
764 |
grub_strcpy(append_line, start); |
765 |
|
766 |
cls(); |
767 |
print_cmdline_message (0); |
768 |
|
769 |
if (get_cmdline(PACKAGE " append> ", |
770 |
append_line, NEW_HEAPSIZE + 1, |
771 |
0, 1)) |
772 |
goto restart; |
773 |
|
774 |
/* have new args; append_line points to the |
775 |
new args and start points to the old |
776 |
args */ |
777 |
|
778 |
i = grub_strlen(start); |
779 |
j = grub_strlen(append_line); |
780 |
|
781 |
/* align rest of commands properly */ |
782 |
memmove (start + j, start + i, |
783 |
((int) append_line) - ((int) start) - (i > j ? i : j)); |
784 |
|
785 |
/* copy command to correct area */ |
786 |
memmove (start, append_line, j); |
787 |
|
788 |
/* set up this entry to boot */ |
789 |
config_entries = NULL; |
790 |
cur_entry = entry_copy; |
791 |
heap = new_heap; |
792 |
|
793 |
break; |
794 |
} |
700 |
#ifdef GRUB_UTIL |
795 |
#ifdef GRUB_UTIL |
701 |
if (c == 'q') |
796 |
if (c == 'q') |
702 |
{ |
797 |
{ |
Lines 753-758
restart:
Link Here
|
753 |
} |
848 |
} |
754 |
|
849 |
|
755 |
|
850 |
|
|
|
851 |
|
852 |
#if 0 |
853 |
/* for debugging */ |
854 |
static void hexdump(unsigned char *buf, unsigned len) |
855 |
{ |
856 |
int i, j = 0; |
857 |
char s[17]; |
858 |
unsigned addr = (unsigned) buf; |
859 |
|
860 |
s[16] = 0; |
861 |
while(len--) { |
862 |
i = buf[j]; |
863 |
i = i & 0xff; |
864 |
s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.'; |
865 |
if(!(j & 15)) { |
866 |
printf("%x ", j + addr); |
867 |
} |
868 |
if(!(j & 7) && (j & 15)) printf(" "); |
869 |
/* stupid grub_printf */ |
870 |
printf("%x", (i >> 4) & 0x0f); |
871 |
printf("%x ", i & 0x0f); |
872 |
if(!(++j & 15)) { |
873 |
printf(" %s\n", s); |
874 |
} |
875 |
} |
876 |
|
877 |
if(j & 15) { |
878 |
s[j & 15] = 0; |
879 |
if(!(j & 8)) printf(" "); |
880 |
i = 1 + 3 * (16 - (j & 15)); |
881 |
while(i--) printf(" "); |
882 |
printf("%s\n", s); |
883 |
} |
884 |
} |
885 |
#endif |
886 |
|
887 |
|
888 |
/* kernel + (grub-)module options */ |
889 |
#define GFX_CMD_BUF_SIZE 512 |
890 |
|
891 |
/* command line separator char */ |
892 |
#define GFX_CMD_SEP 1 |
893 |
|
894 |
/* |
895 |
* Go through config entry and find kernel args, if any. |
896 |
* Put things into buf and return it. |
897 |
*/ |
898 |
static char *get_kernel_args(char *cfg, char *buf) |
899 |
{ |
900 |
int i, j; |
901 |
char *s, *t = "", *p, *t2; |
902 |
|
903 |
*(p = buf) = 0; |
904 |
|
905 |
for(j = 0; ; j++) { |
906 |
s = get_entry(cfg, j, 0); |
907 |
if(!*s) break; |
908 |
if( |
909 |
(!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && |
910 |
(s[6] == ' ' || s[6] == '\t') |
911 |
) { |
912 |
t = skip_to(0, s); |
913 |
t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; |
914 |
if(*t) t = skip_to(0, t); |
915 |
if(t2 && t2 < t) break; /* module is likely a normal initrd -> skip */ |
916 |
i = strlen(t); |
917 |
if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break; |
918 |
*p++ = GFX_CMD_SEP; |
919 |
strcpy(p, t); |
920 |
p += i; |
921 |
|
922 |
continue; |
923 |
} |
924 |
} |
925 |
|
926 |
if(*buf) buf++; /* skip initial separator char */ |
927 |
|
928 |
return buf; |
929 |
} |
930 |
|
931 |
|
932 |
/* |
933 |
* Check header and return code start offset. |
934 |
*/ |
935 |
static unsigned magic_ok(unsigned char *buf) |
936 |
{ |
937 |
if( |
938 |
*(unsigned *) buf == 0x0b2d97f00 && /* magic id */ |
939 |
(buf[4] == 8) /* version 8 */ |
940 |
) { |
941 |
return *(unsigned *) (buf + 8); |
942 |
} |
943 |
|
944 |
return 0; |
945 |
} |
946 |
|
947 |
|
948 |
/* |
949 |
* Search cpio archive for gfx file. |
950 |
*/ |
951 |
static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len) |
952 |
{ |
953 |
unsigned i, fname_len, code_start = 0; |
954 |
|
955 |
*gfx_file_start = 0; |
956 |
|
957 |
for(i = 0; i < len;) { |
958 |
if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { |
959 |
fname_len = *(unsigned short *) (buf + i + 20); |
960 |
*file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); |
961 |
i += 26 + fname_len; |
962 |
i = ((i + 1) & ~1); |
963 |
if((code_start = magic_ok(buf + i))) { |
964 |
*gfx_file_start = i; |
965 |
return code_start; |
966 |
} |
967 |
i += *file_len; |
968 |
i = ((i + 1) & ~1); |
969 |
} |
970 |
else { |
971 |
break; |
972 |
} |
973 |
} |
974 |
|
975 |
return code_start; |
976 |
} |
977 |
|
978 |
static inline unsigned char * stack_ptr(void) |
979 |
{ |
980 |
unsigned char * u; |
981 |
|
982 |
asm("movl %%esp, %0" : "=r" (u)); |
983 |
|
984 |
return u; |
985 |
} |
986 |
|
987 |
static void sleep(int delay) |
988 |
{ |
989 |
int tick, last_tick = currticks(); |
990 |
|
991 |
delay *= 18; |
992 |
|
993 |
while(delay--) { |
994 |
while((tick = currticks()) == last_tick) { } |
995 |
last_tick = tick; |
996 |
} |
997 |
} |
998 |
|
999 |
static void wait_for_key() |
1000 |
{ |
1001 |
printf("Press a key to continue..."); |
1002 |
getkey(); |
1003 |
printf("\r \r"); |
1004 |
} |
1005 |
|
1006 |
|
1007 |
/* |
1008 |
* Leave that much space on the heap. Everything else goes to the graphics |
1009 |
* functions. |
1010 |
* |
1011 |
* 0x2000 is _not_ enough |
1012 |
*/ |
1013 |
#define MIN_HEAP_SIZE 0x4000 |
1014 |
#define MIN_GFX_FREE 0x1000 |
1015 |
|
1016 |
#define SC_BOOTLOADER 0 |
1017 |
#define SC_FAILSAFE 3 |
1018 |
#define SC_SYSCONFIG_SIZE 4 |
1019 |
#define SC_BOOTLOADER_SEG 8 |
1020 |
#define SC_XMEM_0 24 |
1021 |
#define SC_XMEM_1 26 |
1022 |
#define SC_XMEM_2 28 |
1023 |
#define SC_XMEM_3 30 |
1024 |
#define SC_FILE 32 |
1025 |
#define SC_ARCHIVE_START 36 |
1026 |
#define SC_ARCHIVE_END 40 |
1027 |
#define SC_MEM0_START 44 |
1028 |
#define SC_MEM0_END 48 |
1029 |
|
1030 |
/* |
1031 |
* Does normally not return. |
1032 |
*/ |
1033 |
static void |
1034 |
run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, |
1035 |
char *heap, int entryno) |
1036 |
{ |
1037 |
unsigned char *buf, *buf_ext; |
1038 |
unsigned buf_size, buf_ext_size, code_start, file_start; |
1039 |
char *s, *t, *t2, *cfg, *new_config, *p; |
1040 |
char *saved_heap; |
1041 |
int i, j, max_len, gfx_file_size, verbose; |
1042 |
int selected_entry; |
1043 |
gfx_data_t *gfx_data; |
1044 |
char *cmd_buf; |
1045 |
unsigned mem0_start, mem0_end, file_len; |
1046 |
|
1047 |
/* |
1048 |
* check gfx_data_t struct offsets for consistency; gcc will optimize away |
1049 |
* the whole block |
1050 |
*/ |
1051 |
|
1052 |
/* dummy function to make ld fail */ |
1053 |
{ |
1054 |
extern void wrong_struct_size(void); |
1055 |
#define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); |
1056 |
gfx_ofs_check(ok); |
1057 |
gfx_ofs_check(code_seg); |
1058 |
gfx_ofs_check(jmp_table); |
1059 |
gfx_ofs_check(sys_cfg); |
1060 |
gfx_ofs_check(cmdline); |
1061 |
gfx_ofs_check(cmdline_len); |
1062 |
gfx_ofs_check(menu_list); |
1063 |
gfx_ofs_check(menu_default_entry); |
1064 |
gfx_ofs_check(menu_entries); |
1065 |
gfx_ofs_check(menu_entry_len); |
1066 |
gfx_ofs_check(args_list); |
1067 |
gfx_ofs_check(args_entry_len); |
1068 |
gfx_ofs_check(timeout); |
1069 |
#undef gfx_ofs_check |
1070 |
} |
1071 |
|
1072 |
if(!num_entries) return; |
1073 |
|
1074 |
graphics_data = gfx_data = (gfx_data_t *) heap; |
1075 |
heap += sizeof *gfx_data; |
1076 |
memset(gfx_data, 0, sizeof *gfx_data); |
1077 |
|
1078 |
gfx_data->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */ |
1079 |
gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */ |
1080 |
*(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4; /* segment */ |
1081 |
gfx_data->sys_cfg[SC_XMEM_0] = 0x21; /* 1MB @ 2MB */ |
1082 |
gfx_data->sys_cfg[SC_XMEM_1] = 0x41; /* 1MB @ 4MB */ |
1083 |
verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */ |
1084 |
gfx_data->sys_cfg[SC_FAILSAFE] = verbose; |
1085 |
|
1086 |
gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; |
1087 |
|
1088 |
|
1089 |
/* setup command line edit buffer */ |
1090 |
|
1091 |
gfx_data->cmdline_len = 256; |
1092 |
|
1093 |
gfx_data->cmdline = heap; |
1094 |
heap += gfx_data->cmdline_len; |
1095 |
memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); |
1096 |
|
1097 |
cmd_buf = heap; |
1098 |
heap += GFX_CMD_BUF_SIZE; |
1099 |
|
1100 |
/* setup menu entries */ |
1101 |
|
1102 |
for(i = max_len = 0; i < num_entries; i++) { |
1103 |
j = strlen(get_entry(menu_entries, i, 0)); |
1104 |
if(j > max_len) max_len = j; |
1105 |
} |
1106 |
|
1107 |
if(!max_len) return; |
1108 |
|
1109 |
gfx_data->menu_entry_len = max_len + 1; |
1110 |
gfx_data->menu_entries = num_entries; |
1111 |
|
1112 |
gfx_data->menu_list = heap; |
1113 |
heap += gfx_data->menu_entry_len * gfx_data->menu_entries; |
1114 |
|
1115 |
memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); |
1116 |
|
1117 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
1118 |
strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); |
1119 |
} |
1120 |
|
1121 |
gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; |
1122 |
|
1123 |
|
1124 |
/* setup list of kernel args */ |
1125 |
|
1126 |
for(i = max_len = 0; i < num_entries; i++) { |
1127 |
s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf); |
1128 |
j = strlen(s); |
1129 |
if(j > max_len) max_len = j; |
1130 |
} |
1131 |
|
1132 |
gfx_data->args_entry_len = max_len + 1; |
1133 |
|
1134 |
gfx_data->args_list = heap; |
1135 |
heap += gfx_data->args_entry_len * gfx_data->menu_entries; |
1136 |
|
1137 |
memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); |
1138 |
|
1139 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
1140 |
strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf)); |
1141 |
} |
1142 |
|
1143 |
|
1144 |
/* go back here when we no longer need the graphics data */ |
1145 |
saved_heap = heap; |
1146 |
|
1147 |
|
1148 |
/* get memory area to be used by graphics functions */ |
1149 |
|
1150 |
/* use 1MB starting at 2MB as file buffer */ |
1151 |
buf_ext = (unsigned char *) (2 << 20); |
1152 |
buf_ext_size = 1 << 20; |
1153 |
|
1154 |
/* must be 16-byte aligned */ |
1155 |
buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); |
1156 |
|
1157 |
buf_size = stack_ptr() - buf - MIN_HEAP_SIZE; |
1158 |
buf_size &= ~0xf; |
1159 |
|
1160 |
mem0_start = (unsigned) buf; |
1161 |
mem0_end = mem0_start + buf_size; |
1162 |
|
1163 |
if(verbose) { |
1164 |
printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size); |
1165 |
wait_for_key(); |
1166 |
} |
1167 |
|
1168 |
heap += buf_size; |
1169 |
|
1170 |
/* read the file */ |
1171 |
|
1172 |
if(!grub_open(graphics_file)) { |
1173 |
printf("%s: file not found\n", graphics_file); |
1174 |
sleep(5); |
1175 |
heap = saved_heap; |
1176 |
return; |
1177 |
} |
1178 |
|
1179 |
gfx_file_size = grub_read(buf_ext, buf_ext_size); |
1180 |
|
1181 |
grub_close(); |
1182 |
|
1183 |
if(gfx_file_size <= 0) { |
1184 |
printf("%s: read error\n", graphics_file); |
1185 |
sleep(5); |
1186 |
heap = saved_heap; |
1187 |
return; |
1188 |
} |
1189 |
|
1190 |
if(verbose) { |
1191 |
printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size); |
1192 |
wait_for_key(); |
1193 |
} |
1194 |
|
1195 |
/* locate file inside cpio archive */ |
1196 |
if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) { |
1197 |
printf("%s: invalid file format\n", graphics_file); |
1198 |
sleep(5); |
1199 |
heap = saved_heap; |
1200 |
return; |
1201 |
} |
1202 |
|
1203 |
if(verbose) { |
1204 |
printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start); |
1205 |
wait_for_key(); |
1206 |
} |
1207 |
|
1208 |
if(file_len - code_start + MIN_GFX_FREE > buf_size) { |
1209 |
printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size); |
1210 |
sleep(5); |
1211 |
heap = saved_heap; |
1212 |
return; |
1213 |
} |
1214 |
|
1215 |
memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start); |
1216 |
|
1217 |
mem0_start += file_len - code_start; |
1218 |
mem0_start = (mem0_start + 3) & ~3; /* align */ |
1219 |
|
1220 |
/* init interface to graphics functions */ |
1221 |
|
1222 |
*(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start; |
1223 |
*(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext; |
1224 |
*(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size; |
1225 |
*(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start; |
1226 |
*(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end; |
1227 |
|
1228 |
gfx_data->code_seg = (unsigned) buf >> 4; |
1229 |
|
1230 |
if(verbose) { |
1231 |
printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n", |
1232 |
(unsigned) buf_ext + file_start, |
1233 |
(unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size, |
1234 |
mem0_start, mem0_end, gfx_data->code_seg |
1235 |
); |
1236 |
wait_for_key(); |
1237 |
} |
1238 |
|
1239 |
for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { |
1240 |
gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i]; |
1241 |
} |
1242 |
|
1243 |
if(verbose) { |
1244 |
for(i = 0; i < 12; i++) { |
1245 |
printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); |
1246 |
} |
1247 |
|
1248 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
1249 |
printf("\"%s\" -- \"%s\"\n", |
1250 |
gfx_data->menu_list + i * gfx_data->menu_entry_len, |
1251 |
gfx_data->args_list + i * gfx_data->args_entry_len |
1252 |
); |
1253 |
} |
1254 |
|
1255 |
printf("default: \"%s\"\n", gfx_data->menu_default_entry); |
1256 |
wait_for_key(); |
1257 |
} |
1258 |
|
1259 |
/* switch to graphics mode */ |
1260 |
|
1261 |
if(gfx_init(gfx_data)) { |
1262 |
printf("graphics initialization failed\n"); |
1263 |
sleep(5); |
1264 |
heap = saved_heap; |
1265 |
return; |
1266 |
} |
1267 |
|
1268 |
gfx_setup_menu(gfx_data); |
1269 |
|
1270 |
i = gfx_input(gfx_data, &selected_entry); |
1271 |
|
1272 |
/* ESC -> show text menu */ |
1273 |
if(i == 1) { |
1274 |
gfx_done(gfx_data); |
1275 |
grub_timeout = -1; |
1276 |
|
1277 |
heap = saved_heap; |
1278 |
return; |
1279 |
} |
1280 |
|
1281 |
gfx_done(gfx_data); |
1282 |
|
1283 |
heap = saved_heap; /* free most of the graphics data */ |
1284 |
|
1285 |
// printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); |
1286 |
|
1287 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1288 |
|
1289 |
/* for 'savedefault' */ |
1290 |
current_entryno = selected_entry; |
1291 |
|
1292 |
|
1293 |
/* create new config with modified kernel option */ |
1294 |
|
1295 |
cfg = get_entry(config_entries, selected_entry, 1); |
1296 |
|
1297 |
new_config = heap; |
1298 |
|
1299 |
for(p = gfx_data->cmdline, i = 0; ; i++) { |
1300 |
s = get_entry(cfg, i, 0); |
1301 |
if(!*s) { |
1302 |
if(!i) *heap++ = 0; |
1303 |
*heap++ = 0; |
1304 |
break; |
1305 |
} |
1306 |
/* note: must match get_kernel_args() */ |
1307 |
if( |
1308 |
(!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && |
1309 |
(s[6] == ' ' || s[6] == '\t') |
1310 |
) { |
1311 |
t = skip_to(0, s); |
1312 |
t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; |
1313 |
if(*t) t = skip_to(0, t); |
1314 |
if(t2 && t2 < t) { /* module is likely a normal initrd -> skip */ |
1315 |
strcpy(heap, s); |
1316 |
heap += strlen(s) + 1; |
1317 |
continue; |
1318 |
} |
1319 |
memmove(heap, s, t - s); |
1320 |
heap += t - s; |
1321 |
*heap++ = ' '; |
1322 |
while(*p && *p != GFX_CMD_SEP) *heap++ = *p++; |
1323 |
*heap++ = 0; |
1324 |
if(*p == GFX_CMD_SEP) p++; |
1325 |
} |
1326 |
else { |
1327 |
strcpy(heap, s); |
1328 |
heap += strlen(s) + 1; |
1329 |
} |
1330 |
} |
1331 |
|
1332 |
*heap++ = 0; |
1333 |
|
1334 |
// hexdump(new_config, heap - new_config); |
1335 |
// getkey(); |
1336 |
|
1337 |
run_script(new_config, heap); |
1338 |
} |
1339 |
|
1340 |
|
756 |
static int |
1341 |
static int |
757 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
1342 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
758 |
{ |
1343 |
{ |
Lines 827-832
get_line_from_config (char *cmdline, int maxlen, int read_from_file)
Link Here
|
827 |
return pos; |
1412 |
return pos; |
828 |
} |
1413 |
} |
829 |
|
1414 |
|
|
|
1415 |
extern void __savedefault_once_reset(); |
1416 |
|
1417 |
char *wildcard_prefix, *wildcard_suffix; |
1418 |
char wildcard_matches[1024], *end_wildcard_matches; |
1419 |
|
1420 |
static void wildcard_handler(char *name); |
1421 |
|
1422 |
/* Match one directory entry against the current wildcard. If the entry |
1423 |
matches, store it in WILDCARD_MATCHES. Silently ignore entries that |
1424 |
don't fit into WILDCARD_MATCHES anymore. */ |
1425 |
static void |
1426 |
wildcard_handler(char *name) |
1427 |
{ |
1428 |
char *n = name, *p = wildcard_prefix; |
1429 |
|
1430 |
while (*p && *p == *n) |
1431 |
{ |
1432 |
p++; |
1433 |
n++; |
1434 |
} |
1435 |
if (*p) |
1436 |
return; /* prefix mismatch */ |
1437 |
|
1438 |
p = name + grub_strlen (name) - grub_strlen (wildcard_suffix); |
1439 |
/* [n .. p) is the part matching the asterisk */ |
1440 |
|
1441 |
if (p < n || grub_strcmp (p, wildcard_suffix) != 0) |
1442 |
return; /* suffix mismatch */ |
1443 |
|
1444 |
/* store this match */ |
1445 |
if (p - n + 1 > sizeof (wildcard_matches) - |
1446 |
(end_wildcard_matches - wildcard_matches)) |
1447 |
return; /* out of space */ |
1448 |
while (n < p) |
1449 |
*end_wildcard_matches++ = *n++; |
1450 |
*end_wildcard_matches++ = 0; |
1451 |
} |
1452 |
|
1453 |
/* Wildcard expand the GLOB argument. Return NULL upon failure, or |
1454 |
a list of 0-terminated expansions, terminated by a zero-length string. */ |
1455 |
char * |
1456 |
wildcard (char *glob, int *len) |
1457 |
{ |
1458 |
char path[128], *p; |
1459 |
int ret; |
1460 |
|
1461 |
end_wildcard_matches = wildcard_matches; |
1462 |
if (grub_strlen (glob) + 1 > sizeof (path)) { |
1463 |
errnum = ERR_FILELENGTH; |
1464 |
return NULL; /* cannot handle pathnames this long */ |
1465 |
} |
1466 |
grub_strcpy (path, glob); |
1467 |
p = path; |
1468 |
while (*p) |
1469 |
p++; |
1470 |
wildcard_suffix = p; |
1471 |
while (p > path && *p != '/') |
1472 |
p--; |
1473 |
if (*p != '/') |
1474 |
{ |
1475 |
errnum = ERR_BAD_FILETYPE; |
1476 |
return NULL; /* Cannot wildcard device names */ |
1477 |
} |
1478 |
*(++p) = 0; |
1479 |
wildcard_prefix = glob + (p - path); |
1480 |
for (p = wildcard_prefix;; p++) |
1481 |
{ |
1482 |
if (*p == 0) |
1483 |
{ |
1484 |
/* We cannot do exact matches: this cannot be represented in the |
1485 |
result list. */ |
1486 |
return NULL; |
1487 |
} |
1488 |
else if (*p == '*') |
1489 |
{ |
1490 |
*p++ = 0; |
1491 |
wildcard_suffix = p; |
1492 |
break; |
1493 |
} |
1494 |
} |
1495 |
|
1496 |
ret = dir (path, wildcard_handler); |
1497 |
/* restore original argument */ |
1498 |
wildcard_prefix[grub_strlen (wildcard_prefix)] = '*'; |
1499 |
if (!ret) |
1500 |
return NULL; |
1501 |
*len = end_wildcard_matches - wildcard_matches; |
1502 |
return wildcard_matches; |
1503 |
} |
1504 |
|
1505 |
#define skip(str) ((str) + grub_strlen (str) + 1) |
1506 |
|
1507 |
static void inplace_sort (char *str, int len); |
1508 |
|
1509 |
static void |
1510 |
inplace_sort (char *str, int len) |
1511 |
{ |
1512 |
int m, n = 0; |
1513 |
char *s, *t; |
1514 |
|
1515 |
/* we use x as temporary storage */ |
1516 |
char *x = str + len; |
1517 |
|
1518 |
for (s = str; s < x; s = skip (s)) |
1519 |
n++; |
1520 |
|
1521 |
for (; n >= 2; n--) |
1522 |
{ |
1523 |
s = str; |
1524 |
t = skip (s); |
1525 |
|
1526 |
for (m = n; m >= 2; m--) |
1527 |
{ |
1528 |
if (grub_strcmp (s, t) > 0) |
1529 |
{ |
1530 |
int ls = skip (s) - s; |
1531 |
int lt = skip (t) - t; |
1532 |
|
1533 |
memcpy (x, s, ls); |
1534 |
grub_memmove (s + ls, s + lt, t - (s + ls)); |
1535 |
memcpy (s, t, lt); |
1536 |
t = t + lt - ls; |
1537 |
memcpy (t, x, ls); |
1538 |
} |
1539 |
s = t; |
1540 |
t = skip (t); |
1541 |
} |
1542 |
} |
1543 |
} |
1544 |
|
1545 |
#undef skip |
1546 |
|
1547 |
static int this_config_len (const char *config); |
1548 |
static int |
1549 |
this_config_len (const char *config) |
1550 |
{ |
1551 |
const char *c = config; |
1552 |
while (*c) |
1553 |
{ |
1554 |
while (*c) |
1555 |
c++; |
1556 |
c++; |
1557 |
} |
1558 |
c++; |
1559 |
return c - config; |
1560 |
} |
1561 |
|
1562 |
static const char * expand_asterisks (const char *str, int *len, |
1563 |
const char *subst); |
1564 |
|
1565 |
/* Expand all asterisks (*) in a menu entry or commands section with its |
1566 |
substitution. Use a backslash as escape character. */ |
1567 |
static const char * |
1568 |
expand_asterisks (const char *str, int *len, const char *subst) |
1569 |
{ |
1570 |
static char buffer[1024]; |
1571 |
char *b = buffer, escaped = 0; |
1572 |
const char *end = str + *len; |
1573 |
|
1574 |
while (str < end) |
1575 |
{ |
1576 |
if (*str == '*' && !escaped) |
1577 |
{ |
1578 |
if (b - buffer + grub_strlen (subst) > sizeof (buffer)) |
1579 |
{ |
1580 |
errnum = ERR_FILELENGTH; |
1581 |
return NULL; |
1582 |
} |
1583 |
grub_strcpy (b, subst); |
1584 |
b += grub_strlen (subst); |
1585 |
} |
1586 |
else if (*str == '\\' && !escaped) |
1587 |
escaped = 1; |
1588 |
else |
1589 |
{ |
1590 |
escaped = 0; |
1591 |
if (b - buffer + 1 > sizeof (buffer)) |
1592 |
{ |
1593 |
errnum = ERR_FILELENGTH; |
1594 |
return NULL; |
1595 |
} |
1596 |
*b++ = *str; |
1597 |
} |
1598 |
str++; |
1599 |
} |
1600 |
*len = b - buffer; |
1601 |
|
1602 |
return buffer; |
1603 |
} |
830 |
|
1604 |
|
831 |
/* This is the starting function in C. */ |
1605 |
/* This is the starting function in C. */ |
832 |
void |
1606 |
void |
Lines 848-853
cmain (void)
Link Here
|
848 |
init_config (); |
1622 |
init_config (); |
849 |
} |
1623 |
} |
850 |
|
1624 |
|
|
|
1625 |
auto void expand_wildcard_entries (void); |
1626 |
void expand_wildcard_entries (void) |
1627 |
{ |
1628 |
char *config_entry = config_entries; |
1629 |
char *menu_entry = menu_entries; |
1630 |
|
1631 |
while (*menu_entry) |
1632 |
{ |
1633 |
char *command = config_entry; |
1634 |
|
1635 |
do |
1636 |
{ |
1637 |
char *c = command; |
1638 |
const char *w = "wildcard"; |
1639 |
|
1640 |
while (*w && *c == *w) |
1641 |
{ |
1642 |
c++; |
1643 |
w++; |
1644 |
} |
1645 |
if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '=')) |
1646 |
{ |
1647 |
int len, wlen; |
1648 |
|
1649 |
/* This is a wildcard command. Advance to the argument. */ |
1650 |
while (*c == ' ' || *c == '\t' || *c == '=') |
1651 |
c++; |
1652 |
|
1653 |
/* Expand wildcard entry. */ |
1654 |
w = wildcard (c, &wlen); |
1655 |
if (w) |
1656 |
inplace_sort (w, wlen); |
1657 |
|
1658 |
/* Remove the wildcard command from the command section; |
1659 |
it has no meaning beyond the wildcard expansion just |
1660 |
performed. */ |
1661 |
len = grub_strlen (command) + 1; |
1662 |
grub_memmove (command, command + len, |
1663 |
config_len - (command - config_entries)); |
1664 |
config_len -= len; |
1665 |
|
1666 |
while (w && wlen) |
1667 |
{ |
1668 |
/* Insert expansion before the wildcard entry in the |
1669 |
list of entry names. */ |
1670 |
len = grub_strlen (menu_entry) + 1; |
1671 |
const char *x = expand_asterisks (menu_entry, &len, w); |
1672 |
grub_memmove (menu_entry + len, menu_entry, |
1673 |
menu_len - (menu_entry - menu_entries)); |
1674 |
memcpy (menu_entry, x, len); |
1675 |
menu_entry += len; |
1676 |
menu_len += len; |
1677 |
|
1678 |
/* Insert expansion before the wildcard command section |
1679 |
in the list of command sections. */ |
1680 |
len = this_config_len (config_entry); |
1681 |
x = expand_asterisks (config_entry, &len, w); |
1682 |
grub_memmove (config_entry + len, config_entry, |
1683 |
config_len - (config_entry - |
1684 |
config_entries)); |
1685 |
memcpy (config_entry, x, len); |
1686 |
config_entry += len; |
1687 |
config_len += len; |
1688 |
|
1689 |
num_entries++; |
1690 |
wlen -= grub_strlen (w) + 1; |
1691 |
w += grub_strlen (w) + 1; |
1692 |
} |
1693 |
|
1694 |
/* Remove the wildcard command section; it has just |
1695 |
been expanded. */ |
1696 |
len = grub_strlen (menu_entry) + 1; |
1697 |
grub_memmove (menu_entry, menu_entry + len, |
1698 |
menu_len - (menu_entry - menu_entries)); |
1699 |
menu_len -= len; |
1700 |
|
1701 |
len = this_config_len(config_entry); |
1702 |
grub_memmove (config_entry, config_entry + len, |
1703 |
config_len - (config_entry - config_entries)); |
1704 |
config_len -= len; |
1705 |
|
1706 |
num_entries--; |
1707 |
} |
1708 |
command += grub_strlen (command) + 1; |
1709 |
} |
1710 |
while (*command); |
1711 |
menu_entry += grub_strlen (menu_entry) + 1; |
1712 |
config_entry += this_config_len(config_entry); |
1713 |
} |
1714 |
} |
1715 |
|
851 |
/* Initialize the environment for restarting Stage 2. */ |
1716 |
/* Initialize the environment for restarting Stage 2. */ |
852 |
grub_setjmp (restart_env); |
1717 |
grub_setjmp (restart_env); |
853 |
|
1718 |
|
Lines 999-1006
cmain (void)
Link Here
|
999 |
config_len = prev_config_len; |
1864 |
config_len = prev_config_len; |
1000 |
} |
1865 |
} |
1001 |
|
1866 |
|
|
|
1867 |
if (is_preset) |
1868 |
close_preset_menu (); |
1869 |
else |
1870 |
grub_close (); |
1871 |
|
1002 |
menu_entries[menu_len++] = 0; |
1872 |
menu_entries[menu_len++] = 0; |
1003 |
config_entries[config_len++] = 0; |
1873 |
config_entries[config_len++] = 0; |
|
|
1874 |
|
1875 |
expand_wildcard_entries(); |
1876 |
|
1004 |
grub_memmove (config_entries + config_len, menu_entries, |
1877 |
grub_memmove (config_entries + config_len, menu_entries, |
1005 |
menu_len); |
1878 |
menu_len); |
1006 |
menu_entries = config_entries + config_len; |
1879 |
menu_entries = config_entries + config_len; |
Lines 1042-1055
cmain (void)
Link Here
|
1042 |
default_entry = 0; |
1915 |
default_entry = 0; |
1043 |
} |
1916 |
} |
1044 |
|
1917 |
|
1045 |
if (is_preset) |
|
|
1046 |
close_preset_menu (); |
1047 |
else |
1048 |
grub_close (); |
1049 |
} |
1918 |
} |
1050 |
while (is_preset); |
1919 |
while (is_preset); |
1051 |
} |
1920 |
} |
1052 |
|
1921 |
#ifndef SUPPORT_DISKLESS |
|
|
1922 |
__savedefault_once_reset(); |
1923 |
#endif |
1053 |
if (! num_entries) |
1924 |
if (! num_entries) |
1054 |
{ |
1925 |
{ |
1055 |
/* If no acceptable config file, goto command-line, starting |
1926 |
/* If no acceptable config file, goto command-line, starting |
Lines 1059-1067
cmain (void)
Link Here
|
1059 |
} |
1930 |
} |
1060 |
else |
1931 |
else |
1061 |
{ |
1932 |
{ |
1062 |
/* Run menu interface. */ |
1933 |
if (*graphics_file && !password && show_menu && grub_timeout) |
1063 |
run_menu (menu_entries, config_entries, num_entries, |
1934 |
{ |
1064 |
menu_entries + menu_len, default_entry); |
1935 |
run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); |
|
|
1936 |
} |
1937 |
/* Run menu interface. */ |
1938 |
run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); |
1065 |
} |
1939 |
} |
1066 |
} |
1940 |
} |
1067 |
} |
1941 |
} |