|
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 |
} |