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 310-315
Link Here
|
310 |
|
312 |
|
311 |
if (! auth && password) |
313 |
if (! auth && password) |
312 |
{ |
314 |
{ |
|
|
315 |
if (*graphics_file) |
316 |
{ |
317 |
printf ("\ |
318 |
WARNING: graphical menu doesn\'t work\ |
319 |
in conjunction with the password feature\n" ); |
320 |
} |
313 |
printf ("\ |
321 |
printf ("\ |
314 |
Press enter to boot the selected OS or \'p\' to enter a\n\ |
322 |
Press enter to boot the selected OS or \'p\' to enter a\n\ |
315 |
password to unlock the next set of features."); |
323 |
password to unlock the next set of features."); |
Lines 753-758
Link Here
|
753 |
} |
761 |
} |
754 |
|
762 |
|
755 |
|
763 |
|
|
|
764 |
|
765 |
#if 0 |
766 |
/* for debugging */ |
767 |
static void hexdump(unsigned char *buf, unsigned len) |
768 |
{ |
769 |
int i, j = 0; |
770 |
char s[17]; |
771 |
unsigned addr = (unsigned) buf; |
772 |
|
773 |
s[16] = 0; |
774 |
while(len--) { |
775 |
i = buf[j]; |
776 |
i = i & 0xff; |
777 |
s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.'; |
778 |
if(!(j & 15)) { |
779 |
printf("%x ", j + addr); |
780 |
} |
781 |
if(!(j & 7) && (j & 15)) printf(" "); |
782 |
/* stupid grub_printf */ |
783 |
printf("%x", (i >> 4) & 0x0f); |
784 |
printf("%x ", i & 0x0f); |
785 |
if(!(++j & 15)) { |
786 |
printf(" %s\n", s); |
787 |
} |
788 |
} |
789 |
|
790 |
if(j & 15) { |
791 |
s[j & 15] = 0; |
792 |
if(!(j & 8)) printf(" "); |
793 |
i = 1 + 3 * (16 - (j & 15)); |
794 |
while(i--) printf(" "); |
795 |
printf("%s\n", s); |
796 |
} |
797 |
} |
798 |
#endif |
799 |
|
800 |
/* |
801 |
* Go through config entry and find kernel args, if any. |
802 |
*/ |
803 |
static char *get_kernel_args(char *cfg) |
804 |
{ |
805 |
int j; |
806 |
char *s, *t = ""; |
807 |
|
808 |
for(j = 0; ; j++) { |
809 |
s = get_entry(cfg, j, 0); |
810 |
if(!*s) break; |
811 |
if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { |
812 |
t = skip_to(0, s); |
813 |
if(*t) t = skip_to(0, t); |
814 |
break; |
815 |
} |
816 |
} |
817 |
|
818 |
return t; |
819 |
} |
820 |
|
821 |
|
822 |
/* |
823 |
* Check header and return code start offset. |
824 |
*/ |
825 |
static unsigned magic_ok(unsigned char *buf) |
826 |
{ |
827 |
if( |
828 |
*(unsigned *) buf == 0x0b2d97f00 && /* magic id */ |
829 |
buf[4] == 5 /* version 5 */ |
830 |
) { |
831 |
return *(unsigned *) (buf + 8); |
832 |
} |
833 |
|
834 |
return 0; |
835 |
} |
836 |
|
837 |
|
838 |
/* |
839 |
* Search cpio archive for gfx file. |
840 |
*/ |
841 |
static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start) |
842 |
{ |
843 |
unsigned i, fname_len, flen, code_start = 0; |
844 |
|
845 |
*gfx_file_start = 0; |
846 |
|
847 |
for(i = 0; i < len;) { |
848 |
if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { |
849 |
fname_len = *(unsigned short *) (buf + i + 20); |
850 |
flen = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); |
851 |
i += 26 + fname_len; |
852 |
i = ((i + 1) & ~1); |
853 |
if((code_start = magic_ok(buf + i))) { |
854 |
*gfx_file_start = i; |
855 |
return code_start; |
856 |
} |
857 |
i += flen; |
858 |
i = ((i + 1) & ~1); |
859 |
} |
860 |
else { |
861 |
break; |
862 |
} |
863 |
} |
864 |
|
865 |
return code_start; |
866 |
} |
867 |
|
868 |
|
869 |
/* |
870 |
* Leave that much space on the heap. Everything else goes to the graphics |
871 |
* functions. |
872 |
* |
873 |
* 0x2000 is _not_ enough |
874 |
*/ |
875 |
#define MIN_HEAP_SIZE 0x4000 |
876 |
|
877 |
/* gfx code needs at least this much free memory */ |
878 |
#define MIN_GFX_FREE 0xc000 |
879 |
|
880 |
/* |
881 |
* Does normally not return. |
882 |
*/ |
883 |
static void |
884 |
run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, |
885 |
char *heap, int entryno) |
886 |
{ |
887 |
unsigned char *buf; |
888 |
unsigned u, buf_size, code_start, file_start; |
889 |
char *s, *t, *cfg, *new_config; |
890 |
char *saved_heap; |
891 |
int i, j, max_len; |
892 |
int selected_entry; |
893 |
gfx_data_t *gfx_data; |
894 |
|
895 |
/* |
896 |
* check gfx_data_t struct offsets for consistency; gcc will optimize away |
897 |
* the whole block |
898 |
*/ |
899 |
|
900 |
/* dummy function to make ld fail */ |
901 |
{ |
902 |
extern void wrong_struct_size(void); |
903 |
#define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); |
904 |
gfx_ofs_check(ok); |
905 |
gfx_ofs_check(mem_start); |
906 |
gfx_ofs_check(mem_cur); |
907 |
gfx_ofs_check(mem_max); |
908 |
gfx_ofs_check(code_seg); |
909 |
gfx_ofs_check(jmp_table); |
910 |
gfx_ofs_check(sys_cfg); |
911 |
gfx_ofs_check(cmdline); |
912 |
gfx_ofs_check(cmdline_len); |
913 |
gfx_ofs_check(menu_list); |
914 |
gfx_ofs_check(menu_default_entry); |
915 |
gfx_ofs_check(menu_entries); |
916 |
gfx_ofs_check(menu_entry_len); |
917 |
gfx_ofs_check(args_list); |
918 |
gfx_ofs_check(args_entry_len); |
919 |
gfx_ofs_check(timeout); |
920 |
gfx_ofs_check(mem_file); |
921 |
gfx_ofs_check(mem_align); |
922 |
#undef gfx_ofs_check |
923 |
} |
924 |
|
925 |
if(!num_entries) return; |
926 |
|
927 |
graphics_data = gfx_data = (gfx_data_t *) heap; |
928 |
heap += sizeof *gfx_data; |
929 |
memset(gfx_data, 0, sizeof *gfx_data); |
930 |
|
931 |
gfx_data->sys_cfg[0] = 2; /* bootloader: grub */ |
932 |
gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; |
933 |
|
934 |
|
935 |
/* setup command line edit buffer */ |
936 |
|
937 |
gfx_data->cmdline_len = 256; |
938 |
|
939 |
gfx_data->cmdline = heap; |
940 |
heap += gfx_data->cmdline_len; |
941 |
memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); |
942 |
|
943 |
|
944 |
/* setup menu entries */ |
945 |
|
946 |
for(i = max_len = 0; i < num_entries; i++) { |
947 |
j = strlen(get_entry(menu_entries, i, 0)); |
948 |
if(j > max_len) max_len = j; |
949 |
} |
950 |
|
951 |
if(!max_len) return; |
952 |
|
953 |
gfx_data->menu_entry_len = max_len + 1; |
954 |
gfx_data->menu_entries = num_entries; |
955 |
|
956 |
gfx_data->menu_list = heap; |
957 |
heap += gfx_data->menu_entry_len * gfx_data->menu_entries; |
958 |
|
959 |
memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); |
960 |
|
961 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
962 |
strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); |
963 |
} |
964 |
|
965 |
gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; |
966 |
|
967 |
|
968 |
/* setup list of kernel args */ |
969 |
|
970 |
for(i = max_len = 0; i < num_entries; i++) { |
971 |
s = get_kernel_args(get_entry(config_entries, i, 1)); |
972 |
j = strlen(s); |
973 |
if(j > max_len) max_len = j; |
974 |
} |
975 |
|
976 |
gfx_data->args_entry_len = max_len + 1; |
977 |
|
978 |
gfx_data->args_list = heap; |
979 |
heap += gfx_data->args_entry_len * gfx_data->menu_entries; |
980 |
|
981 |
memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); |
982 |
|
983 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
984 |
strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1))); |
985 |
} |
986 |
|
987 |
|
988 |
/* go back here when we no longer need the graphics data */ |
989 |
saved_heap = heap; |
990 |
|
991 |
|
992 |
/* get memory area to be used by graphics functions */ |
993 |
|
994 |
buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); |
995 |
|
996 |
buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE; |
997 |
buf_size &= ~0xf; |
998 |
|
999 |
/* too small */ |
1000 |
if(buf_size < 0x10000) return; |
1001 |
|
1002 |
gfx_data->mem_start = (unsigned) buf; |
1003 |
gfx_data->mem_max = gfx_data->mem_start + buf_size; |
1004 |
|
1005 |
#if 0 |
1006 |
printf("graphics menu\n"); |
1007 |
printf( |
1008 |
"heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n", |
1009 |
heap, gfx_data->mem_start, buf_size, graphics_file |
1010 |
); |
1011 |
getkey(); |
1012 |
#endif |
1013 |
|
1014 |
heap += buf_size; |
1015 |
|
1016 |
|
1017 |
/* read the file */ |
1018 |
|
1019 |
if(!grub_open(graphics_file)) { |
1020 |
printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file); |
1021 |
getkey(); |
1022 |
return; |
1023 |
} |
1024 |
|
1025 |
i = grub_read(buf, buf_size); |
1026 |
|
1027 |
grub_close(); |
1028 |
|
1029 |
if(i <= 0) { |
1030 |
printf("error reading \"%s\", press a key to continue...\n", graphics_file); |
1031 |
getkey(); |
1032 |
return; |
1033 |
} |
1034 |
|
1035 |
/* besides the file, we need some working memory, too */ |
1036 |
if(i + MIN_GFX_FREE + 0x0f >= (int) buf_size) { |
1037 |
printf("file \"%s\" too large, press a key to continue...\n", graphics_file); |
1038 |
getkey(); |
1039 |
return; |
1040 |
} |
1041 |
|
1042 |
gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */ |
1043 |
|
1044 |
#if 0 |
1045 |
printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur); |
1046 |
getkey(); |
1047 |
#endif |
1048 |
|
1049 |
|
1050 |
/* locate file inside cpio archive */ |
1051 |
if(!(code_start = find_file(buf, i, &file_start))) { |
1052 |
printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file); |
1053 |
getkey(); |
1054 |
return; |
1055 |
} |
1056 |
|
1057 |
|
1058 |
/* align it */ |
1059 |
u = (-(code_start + gfx_data->mem_start + file_start)) & 0x0f; |
1060 |
gfx_data->mem_align = gfx_data->mem_start + u; |
1061 |
gfx_data->mem_file = gfx_data->mem_align + file_start; |
1062 |
if(u) { |
1063 |
memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i); |
1064 |
} |
1065 |
|
1066 |
/* init interface to graphics functions */ |
1067 |
|
1068 |
code_start += gfx_data->mem_file; |
1069 |
|
1070 |
#if 0 |
1071 |
printf("code_start: 0x%x, file_start: 0x%x, mem_align = 0x%x, mem_file = 0x%x\n", |
1072 |
code_start, file_start, gfx_data->mem_align, gfx_data->mem_file |
1073 |
); |
1074 |
getkey(); |
1075 |
#endif |
1076 |
|
1077 |
gfx_data->code_seg = code_start >> 4; |
1078 |
|
1079 |
#if 0 |
1080 |
printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg); |
1081 |
#endif |
1082 |
|
1083 |
for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { |
1084 |
gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) code_start)[i]; |
1085 |
} |
1086 |
|
1087 |
#if 0 |
1088 |
for(i = 0; i < 12; i++) { |
1089 |
printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); |
1090 |
} |
1091 |
|
1092 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
1093 |
printf(">%s< - >%s<\n", |
1094 |
gfx_data->menu_list + i * gfx_data->menu_entry_len, |
1095 |
gfx_data->args_list + i * gfx_data->args_entry_len |
1096 |
); |
1097 |
} |
1098 |
|
1099 |
printf("def: >%s<\n", gfx_data->menu_default_entry); |
1100 |
#endif |
1101 |
|
1102 |
|
1103 |
/* switch to graphics mode */ |
1104 |
|
1105 |
if(gfx_init(gfx_data)) { |
1106 |
#if 0 |
1107 |
printf("gfx_init failed\n"); |
1108 |
getkey(); |
1109 |
#endif |
1110 |
return; |
1111 |
} |
1112 |
|
1113 |
gfx_setup_menu(gfx_data); |
1114 |
|
1115 |
i = gfx_input(gfx_data, &selected_entry); |
1116 |
|
1117 |
/* ESC -> show text menu */ |
1118 |
if(i == 1) { |
1119 |
gfx_done(gfx_data); |
1120 |
grub_timeout = -1; |
1121 |
|
1122 |
return; |
1123 |
} |
1124 |
|
1125 |
gfx_done(gfx_data); |
1126 |
|
1127 |
heap = saved_heap; /* free most of the graphics data */ |
1128 |
|
1129 |
// printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); |
1130 |
|
1131 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1132 |
|
1133 |
|
1134 |
/* create new config with modified kernel option */ |
1135 |
|
1136 |
cfg = get_entry(config_entries, selected_entry, 1); |
1137 |
|
1138 |
new_config = heap; |
1139 |
|
1140 |
for(i = 0; ; i++) { |
1141 |
s = get_entry(cfg, i, 0); |
1142 |
if(!*s) { |
1143 |
if(!i) *heap++ = 0; |
1144 |
*heap++ = 0; |
1145 |
break; |
1146 |
} |
1147 |
if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { |
1148 |
t = skip_to(0, s); |
1149 |
if(*t) t = skip_to(0, t); |
1150 |
memmove(heap, s, t - s); |
1151 |
heap += t - s; |
1152 |
*heap++ = ' '; |
1153 |
strcpy(heap, gfx_data->cmdline); |
1154 |
heap += strlen(gfx_data->cmdline) + 1; |
1155 |
} |
1156 |
else { |
1157 |
strcpy(heap, s); |
1158 |
heap += strlen(s) + 1; |
1159 |
} |
1160 |
} |
1161 |
|
1162 |
*heap++ = 0; |
1163 |
|
1164 |
// hexdump(new_config, heap - new_config); |
1165 |
// getkey(); |
1166 |
|
1167 |
run_script(new_config, heap); |
1168 |
} |
1169 |
|
1170 |
|
756 |
static int |
1171 |
static int |
757 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
1172 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
758 |
{ |
1173 |
{ |
Lines 1058-1066
Link Here
|
1058 |
} |
1473 |
} |
1059 |
else |
1474 |
else |
1060 |
{ |
1475 |
{ |
1061 |
/* Run menu interface. */ |
1476 |
if (*graphics_file && !password && show_menu && grub_timeout) |
1062 |
run_menu (menu_entries, config_entries, num_entries, |
1477 |
{ |
1063 |
menu_entries + menu_len, default_entry); |
1478 |
run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); |
|
|
1479 |
} |
1480 |
/* Run menu interface. */ |
1481 |
run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); |
1064 |
} |
1482 |
} |
1065 |
} |
1483 |
} |
1066 |
} |
1484 |
} |