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 |
/* for debugging */ |
766 |
static void hexdump(unsigned char *buf, unsigned len) |
767 |
{ |
768 |
int i, j = 0; |
769 |
char s[17]; |
770 |
unsigned addr = (unsigned) buf; |
771 |
|
772 |
s[16] = 0; |
773 |
while(len--) { |
774 |
i = buf[j]; |
775 |
i = i & 0xff; |
776 |
s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.'; |
777 |
if(!(j & 15)) { |
778 |
printf("%x ", j + addr); |
779 |
} |
780 |
if(!(j & 7) && (j & 15)) printf(" "); |
781 |
/* stupid grub_printf */ |
782 |
printf("%x", (i >> 4) & 0x0f); |
783 |
printf("%x ", i & 0x0f); |
784 |
if(!(++j & 15)) { |
785 |
printf(" %s\n", s); |
786 |
} |
787 |
} |
788 |
|
789 |
if(j & 15) { |
790 |
s[j & 15] = 0; |
791 |
if(!(j & 8)) printf(" "); |
792 |
i = 1 + 3 * (16 - (j & 15)); |
793 |
while(i--) printf(" "); |
794 |
printf("%s\n", s); |
795 |
} |
796 |
} |
797 |
|
798 |
|
799 |
/* |
800 |
* Go through config entry and find kernel args, if any. |
801 |
*/ |
802 |
static char *get_kernel_args(char *cfg) |
803 |
{ |
804 |
int j; |
805 |
char *s, *t = ""; |
806 |
|
807 |
for(j = 0; ; j++) { |
808 |
s = get_entry(cfg, j, 0); |
809 |
if(!*s) break; |
810 |
if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { |
811 |
t = skip_to(0, s); |
812 |
if(*t) t = skip_to(0, t); |
813 |
break; |
814 |
} |
815 |
} |
816 |
|
817 |
return t; |
818 |
} |
819 |
|
820 |
|
821 |
/* |
822 |
* Leave that much space on the heap. Everything else goes to the graphics |
823 |
* functions. |
824 |
* |
825 |
* 0x2000 is _not_ enough |
826 |
*/ |
827 |
#define MIN_HEAP_SIZE 0x4000 |
828 |
|
829 |
/* gfx code needs at least this much free memory */ |
830 |
#define MIN_GFX_FREE 0xc000 |
831 |
|
832 |
/* |
833 |
* Does normally not return. |
834 |
*/ |
835 |
static void |
836 |
run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, |
837 |
char *heap, int entryno) |
838 |
{ |
839 |
unsigned char *buf; |
840 |
unsigned buf_size, code_start; |
841 |
char *s, *t, *cfg, *new_config; |
842 |
char *saved_heap; |
843 |
int i, j, max_len; |
844 |
int selected_entry; |
845 |
gfx_data_t *gfx_data; |
846 |
|
847 |
/* |
848 |
* check gfx_data_t struct offsets for consistency; gcc will optimize away |
849 |
* the whole block |
850 |
*/ |
851 |
|
852 |
/* dummy function to make ld fail */ |
853 |
{ |
854 |
extern void wrong_struct_size(void); |
855 |
#define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); |
856 |
gfx_ofs_check(ok); |
857 |
gfx_ofs_check(mem_start); |
858 |
gfx_ofs_check(mem_cur); |
859 |
gfx_ofs_check(mem_max); |
860 |
gfx_ofs_check(code_seg); |
861 |
gfx_ofs_check(jmp_table); |
862 |
gfx_ofs_check(sys_cfg); |
863 |
gfx_ofs_check(cmdline); |
864 |
gfx_ofs_check(cmdline_len); |
865 |
gfx_ofs_check(menu_list); |
866 |
gfx_ofs_check(menu_default_entry); |
867 |
gfx_ofs_check(menu_entries); |
868 |
gfx_ofs_check(menu_entry_len); |
869 |
gfx_ofs_check(args_list); |
870 |
gfx_ofs_check(args_entry_len); |
871 |
gfx_ofs_check(timeout); |
872 |
#undef gfx_ofs_check |
873 |
} |
874 |
|
875 |
if(!num_entries) return; |
876 |
|
877 |
graphics_data = gfx_data = (gfx_data_t *) heap; |
878 |
heap += sizeof *gfx_data; |
879 |
memset(gfx_data, 0, sizeof *gfx_data); |
880 |
|
881 |
gfx_data->sys_cfg[0] = 2; /* bootloader: grub */ |
882 |
gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; |
883 |
|
884 |
|
885 |
/* setup command line edit buffer */ |
886 |
|
887 |
gfx_data->cmdline_len = 256; |
888 |
|
889 |
gfx_data->cmdline = heap; |
890 |
heap += gfx_data->cmdline_len; |
891 |
memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); |
892 |
|
893 |
|
894 |
/* setup menu entries */ |
895 |
|
896 |
for(i = max_len = 0; i < num_entries; i++) { |
897 |
j = strlen(get_entry(menu_entries, i, 0)); |
898 |
if(j > max_len) max_len = j; |
899 |
} |
900 |
|
901 |
if(!max_len) return; |
902 |
|
903 |
gfx_data->menu_entry_len = max_len + 1; |
904 |
gfx_data->menu_entries = num_entries; |
905 |
|
906 |
gfx_data->menu_list = heap; |
907 |
heap += gfx_data->menu_entry_len * gfx_data->menu_entries; |
908 |
|
909 |
memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); |
910 |
|
911 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
912 |
strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); |
913 |
} |
914 |
|
915 |
gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; |
916 |
|
917 |
|
918 |
/* setup list of kernel args */ |
919 |
|
920 |
for(i = max_len = 0; i < num_entries; i++) { |
921 |
s = get_kernel_args(get_entry(config_entries, i, 1)); |
922 |
j = strlen(s); |
923 |
if(j > max_len) max_len = j; |
924 |
} |
925 |
|
926 |
gfx_data->args_entry_len = max_len + 1; |
927 |
|
928 |
gfx_data->args_list = heap; |
929 |
heap += gfx_data->args_entry_len * gfx_data->menu_entries; |
930 |
|
931 |
memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); |
932 |
|
933 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
934 |
strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1))); |
935 |
} |
936 |
|
937 |
|
938 |
/* go back here when we no longer need the graphics data */ |
939 |
saved_heap = heap; |
940 |
|
941 |
|
942 |
/* get memory area to be used by graphics functions */ |
943 |
|
944 |
buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); |
945 |
|
946 |
buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE; |
947 |
buf_size &= ~0xf; |
948 |
|
949 |
/* too small */ |
950 |
if(buf_size < 0x10000) return; |
951 |
|
952 |
gfx_data->mem_start = (unsigned) buf; |
953 |
gfx_data->mem_max = gfx_data->mem_start + buf_size; |
954 |
|
955 |
#if 0 |
956 |
printf("graphics menu\n"); |
957 |
printf( |
958 |
"heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n", |
959 |
heap, gfx_data->mem_start, buf_size, graphics_file |
960 |
); |
961 |
getkey(); |
962 |
#endif |
963 |
|
964 |
heap += buf_size; |
965 |
|
966 |
|
967 |
/* read the file */ |
968 |
|
969 |
if(!grub_open(graphics_file)) { |
970 |
printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file); |
971 |
getkey(); |
972 |
return; |
973 |
} |
974 |
|
975 |
i = grub_read(buf, buf_size); |
976 |
|
977 |
grub_close(); |
978 |
|
979 |
if(i <= 0) { |
980 |
printf("error reading \"%s\", press a key to continue...\n", graphics_file); |
981 |
getkey(); |
982 |
return; |
983 |
} |
984 |
|
985 |
/* besides the file, we need some working memory, too */ |
986 |
if(i + MIN_GFX_FREE >= buf_size) { |
987 |
printf("file \"%s\" too large, press a key to continue...\n", graphics_file); |
988 |
getkey(); |
989 |
return; |
990 |
} |
991 |
|
992 |
gfx_data->mem_cur = gfx_data->mem_start + ((i + 3) & ~3); /* align it */ |
993 |
|
994 |
// printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur); |
995 |
// getkey(); |
996 |
|
997 |
if( |
998 |
*(unsigned *) buf != 0x0b2d97f00 || /* magic id */ |
999 |
buf[4] != 4 || /* version 4 */ |
1000 |
!(code_start = *(unsigned *) (buf + 8)) || |
1001 |
(code_start & 0xf) /* check alignment */ |
1002 |
) { |
1003 |
printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file); |
1004 |
getkey(); |
1005 |
return; |
1006 |
} |
1007 |
|
1008 |
|
1009 |
/* init interface to graphics functions */ |
1010 |
|
1011 |
code_start += gfx_data->mem_start; |
1012 |
|
1013 |
gfx_data->code_seg = code_start >> 4; |
1014 |
|
1015 |
// printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg); |
1016 |
|
1017 |
for(i = 0; i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { |
1018 |
gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) code_start)[i]; |
1019 |
} |
1020 |
|
1021 |
#if 0 |
1022 |
for(i = 0; i < 12; i++) { |
1023 |
printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); |
1024 |
} |
1025 |
|
1026 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
1027 |
printf(">%s< - >%s<\n", |
1028 |
gfx_data->menu_list + i * gfx_data->menu_entry_len, |
1029 |
gfx_data->args_list + i * gfx_data->args_entry_len |
1030 |
); |
1031 |
} |
1032 |
|
1033 |
printf("def: >%s<\n", gfx_data->menu_default_entry); |
1034 |
#endif |
1035 |
|
1036 |
|
1037 |
/* switch to graphics mode */ |
1038 |
|
1039 |
if(gfx_init(gfx_data)) return; |
1040 |
|
1041 |
gfx_setup_menu(gfx_data); |
1042 |
|
1043 |
i = gfx_input(gfx_data, &selected_entry); |
1044 |
|
1045 |
/* ESC -> show text menu */ |
1046 |
if(i == 1) { |
1047 |
gfx_done(gfx_data); |
1048 |
grub_timeout = -1; |
1049 |
|
1050 |
return; |
1051 |
} |
1052 |
|
1053 |
gfx_done(gfx_data); |
1054 |
|
1055 |
heap = saved_heap; /* free most of the graphics data */ |
1056 |
|
1057 |
// printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); |
1058 |
|
1059 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1060 |
|
1061 |
|
1062 |
/* create new config with modified kernel option */ |
1063 |
|
1064 |
cfg = get_entry(config_entries, selected_entry, 1); |
1065 |
|
1066 |
new_config = heap; |
1067 |
|
1068 |
for(i = 0; ; i++) { |
1069 |
s = get_entry(cfg, i, 0); |
1070 |
if(!*s) { |
1071 |
if(!i) *heap++ = 0; |
1072 |
*heap++ = 0; |
1073 |
break; |
1074 |
} |
1075 |
if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { |
1076 |
t = skip_to(0, s); |
1077 |
if(*t) t = skip_to(0, t); |
1078 |
memmove(heap, s, t - s); |
1079 |
heap += t - s; |
1080 |
*heap++ = ' '; |
1081 |
strcpy(heap, gfx_data->cmdline); |
1082 |
heap += strlen(gfx_data->cmdline) + 1; |
1083 |
} |
1084 |
else { |
1085 |
strcpy(heap, s); |
1086 |
heap += strlen(s) + 1; |
1087 |
} |
1088 |
} |
1089 |
|
1090 |
*heap++ = 0; |
1091 |
|
1092 |
// hexdump(new_config, heap - new_config); |
1093 |
// getkey(); |
1094 |
|
1095 |
run_script(new_config, heap); |
1096 |
} |
1097 |
|
1098 |
|
756 |
static int |
1099 |
static int |
757 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
1100 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
758 |
{ |
1101 |
{ |
Lines 1058-1066
Link Here
|
1058 |
} |
1401 |
} |
1059 |
else |
1402 |
else |
1060 |
{ |
1403 |
{ |
1061 |
/* Run menu interface. */ |
1404 |
if (*graphics_file && !password && show_menu && grub_timeout) |
1062 |
run_menu (menu_entries, config_entries, num_entries, |
1405 |
{ |
1063 |
menu_entries + menu_len, default_entry); |
1406 |
run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); |
|
|
1407 |
} |
1408 |
/* Run menu interface. */ |
1409 |
run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); |
1064 |
} |
1410 |
} |
1065 |
} |
1411 |
} |
1066 |
} |
1412 |
} |