Line
Link Here
|
0 |
-- docs/grub.texi |
0 |
++ docs/grub.texi |
Lines 2118-2123
Link Here
|
2118 |
* default:: Set the default entry |
2118 |
* default:: Set the default entry |
2119 |
* fallback:: Set the fallback entry |
2119 |
* fallback:: Set the fallback entry |
2120 |
* hiddenmenu:: Hide the menu interface |
2120 |
* hiddenmenu:: Hide the menu interface |
|
|
2121 |
* gfxmenu:: Use graphical menu interface |
2121 |
* timeout:: Set the timeout |
2122 |
* timeout:: Set the timeout |
2122 |
* title:: Start a menu entry |
2123 |
* title:: Start a menu entry |
2123 |
@end menu |
2124 |
@end menu |
Lines 2150-2155
Link Here
|
2150 |
@end deffn |
2151 |
@end deffn |
2151 |
|
2152 |
|
2152 |
|
2153 |
|
|
|
2154 |
@node gfxmenu |
2155 |
@subsection gfxmenu |
2156 |
|
2157 |
@deffn Command gfxmenu file |
2158 |
Use the graphical menu interface. The graphics data are taken from |
2159 |
@var{file} and must be created using 'mkbootmsg' from the gfxboot package. |
2160 |
@end deffn |
2161 |
|
2162 |
|
2153 |
@node hiddenmenu |
2163 |
@node hiddenmenu |
2154 |
@subsection hiddenmenu |
2164 |
@subsection hiddenmenu |
2155 |
|
2165 |
|
2156 |
-- grub/asmstub.c |
2166 |
++ grub/asmstub.c |
Lines 498-503
Link Here
|
498 |
return 0; |
498 |
return 0; |
499 |
} |
499 |
} |
500 |
|
500 |
|
|
|
501 |
/* graphical menu functions . */ |
502 |
int |
503 |
gfx_init (gfx_data_t *gfx_data) |
504 |
{ |
505 |
return 0; |
506 |
} |
507 |
|
508 |
int |
509 |
gfx_done (gfx_data_t *gfx_data) |
510 |
{ |
511 |
return 0; |
512 |
} |
513 |
|
514 |
int |
515 |
gfx_input (gfx_data_t *gfx_data, int *menu_entry) |
516 |
{ |
517 |
return 0; |
518 |
} |
519 |
|
520 |
int |
521 |
gfx_setup_menu (gfx_data_t *gfx_data) |
522 |
{ |
523 |
return 0; |
524 |
} |
525 |
|
526 |
|
501 |
/* low-level timing info */ |
527 |
/* low-level timing info */ |
502 |
int |
528 |
int |
503 |
getrtsecs (void) |
529 |
getrtsecs (void) |
504 |
-- stage2/asm.S |
530 |
++ stage2/asm.S |
Lines 1614-1619
Link Here
|
1614 |
popl %ebp |
1614 |
popl %ebp |
1615 |
ret |
1615 |
ret |
1616 |
|
1616 |
|
|
|
1617 |
|
1618 |
/* |
1619 |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
1620 |
* |
1621 |
* graphical menu functions |
1622 |
* |
1623 |
*/ |
1624 |
|
1625 |
/* |
1626 |
* int gfx_init (gfx_data_t *gfx_data) |
1627 |
* |
1628 |
* init gfx things |
1629 |
* |
1630 |
* return vales: |
1631 |
* 0: ok |
1632 |
* 1: failed |
1633 |
* sets gfx_data->ok |
1634 |
*/ |
1635 |
|
1636 |
ENTRY(gfx_init) |
1637 |
pushl %ebp |
1638 |
movl %esp, %ebp |
1639 |
|
1640 |
pushl %edi |
1641 |
pushl %esi |
1642 |
pushl %ebx |
1643 |
|
1644 |
movl 8(%ebp),%edx |
1645 |
movl %edx,%edi |
1646 |
leal gfx_ofs_sys_cfg(%edx),%esi |
1647 |
andl $0xf,%edi |
1648 |
shrl $4,%edx |
1649 |
|
1650 |
pushl %ebp |
1651 |
|
1652 |
call EXT_C(prot_to_real) |
1653 |
.code16 |
1654 |
|
1655 |
pushw %ds |
1656 |
movw %dx,%ds |
1657 |
|
1658 |
lcall *gfx_ofs_jmp_table + 4 * 0 (%di) |
1659 |
|
1660 |
sbbl %ebx,%ebx |
1661 |
negl %ebx |
1662 |
|
1663 |
popw %ds |
1664 |
|
1665 |
DATA32 call EXT_C(real_to_prot) |
1666 |
.code32 |
1667 |
|
1668 |
popl %ebp |
1669 |
|
1670 |
movl %ebx,%eax |
1671 |
xorl $1,%ebx |
1672 |
movl 8(%ebp),%edx |
1673 |
movl %ebx,gfx_ofs_ok(%edx) |
1674 |
|
1675 |
popl %ebx |
1676 |
popl %esi |
1677 |
popl %edi |
1678 |
|
1679 |
popl %ebp |
1680 |
ret |
1681 |
|
1682 |
|
1683 |
/* |
1684 |
* int gfx_done (gfx_data_t *gfx_data) |
1685 |
* |
1686 |
* shut down gfx things |
1687 |
* |
1688 |
* return vales: |
1689 |
* always 0 |
1690 |
* sets gfx_data->ok |
1691 |
*/ |
1692 |
|
1693 |
ENTRY(gfx_done) |
1694 |
pushl %ebp |
1695 |
movl %esp, %ebp |
1696 |
|
1697 |
pushl %edi |
1698 |
pushl %esi |
1699 |
pushl %ebx |
1700 |
|
1701 |
movl 8(%ebp),%edx |
1702 |
movl %edx,%ebx |
1703 |
andl $0xf,%ebx |
1704 |
shrl $4,%edx |
1705 |
|
1706 |
pushl %ebp |
1707 |
|
1708 |
call EXT_C(prot_to_real) |
1709 |
.code16 |
1710 |
|
1711 |
pushw %ds |
1712 |
|
1713 |
movw %dx,%ds |
1714 |
|
1715 |
lcall *gfx_ofs_jmp_table + 4 * 1 (%bx) |
1716 |
|
1717 |
popw %ds |
1718 |
|
1719 |
DATA32 call EXT_C(real_to_prot) |
1720 |
.code32 |
1721 |
|
1722 |
popl %ebp |
1723 |
|
1724 |
xorl %eax,%eax |
1725 |
movl 8(%ebp),%edx |
1726 |
movl %eax,gfx_ofs_ok(%edx) |
1727 |
|
1728 |
popl %ebx |
1729 |
popl %esi |
1730 |
popl %edi |
1731 |
|
1732 |
popl %ebp |
1733 |
ret |
1734 |
|
1735 |
|
1736 |
/* |
1737 |
* int gfx_input (gfx_data_t *gfx_data, int *menu_entry) |
1738 |
* |
1739 |
* let user enter a command line |
1740 |
* |
1741 |
* uses gfx_data->cmdline as buffer |
1742 |
* |
1743 |
* return values: |
1744 |
* 1: abort |
1745 |
* 2: boot |
1746 |
* menu_entry: selected entry |
1747 |
*/ |
1748 |
|
1749 |
ENTRY(gfx_input) |
1750 |
pushl %ebp |
1751 |
movl %esp, %ebp |
1752 |
|
1753 |
pushl %edi |
1754 |
pushl %esi |
1755 |
pushl %ebx |
1756 |
|
1757 |
movl 8(%ebp),%edx |
1758 |
movl %edx,%ebx |
1759 |
leal gfx_ofs_sys_cfg(%edx),%esi |
1760 |
andl $0xf,%ebx |
1761 |
shrl $4,%edx |
1762 |
|
1763 |
pushl %ebp |
1764 |
|
1765 |
call EXT_C(prot_to_real) |
1766 |
.code16 |
1767 |
|
1768 |
pushw %ds |
1769 |
|
1770 |
movw %dx,%ds |
1771 |
|
1772 |
movl gfx_ofs_cmdline(%bx),%edi |
1773 |
movl gfx_ofs_cmdline_len(%bx),%ecx |
1774 |
movl gfx_ofs_timeout(%bx),%eax |
1775 |
imull $18,%eax |
1776 |
|
1777 |
lcall *gfx_ofs_jmp_table + 4 * 2 (%bx) |
1778 |
|
1779 |
movl %eax,%ecx |
1780 |
|
1781 |
popw %ds |
1782 |
|
1783 |
DATA32 call EXT_C(real_to_prot) |
1784 |
.code32 |
1785 |
|
1786 |
popl %ebp |
1787 |
|
1788 |
movl 12(%ebp),%edx |
1789 |
movl %ebx,(%edx) |
1790 |
|
1791 |
movl %ecx,%eax |
1792 |
|
1793 |
popl %ebx |
1794 |
popl %esi |
1795 |
popl %edi |
1796 |
|
1797 |
popl %ebp |
1798 |
ret |
1799 |
|
1800 |
|
1801 |
/* |
1802 |
* int gfx_setup_menu (gfx_data_t *gfx_data) |
1803 |
* |
1804 |
* draw boot menu |
1805 |
* |
1806 |
* return values: |
1807 |
* always 0 |
1808 |
*/ |
1809 |
|
1810 |
/* menu entry descriptor */ |
1811 |
#define menu_entries 0 |
1812 |
#define menu_default 2 /* seg:ofs */ |
1813 |
#define menu_ent_list 6 /* seg:ofs */ |
1814 |
#define menu_ent_size 10 |
1815 |
#define menu_arg_list 12 /* seg:ofs */ |
1816 |
#define menu_arg_size 16 |
1817 |
#define sizeof_menu_desc 18 |
1818 |
|
1819 |
ENTRY(gfx_setup_menu) |
1820 |
pushl %ebp |
1821 |
movl %esp, %ebp |
1822 |
|
1823 |
pushl %edi |
1824 |
pushl %esi |
1825 |
pushl %ebx |
1826 |
|
1827 |
movl 8(%ebp),%edx |
1828 |
movl %edx,%ebx |
1829 |
andl $0xf,%ebx |
1830 |
shrl $4,%edx |
1831 |
|
1832 |
call EXT_C(prot_to_real) |
1833 |
.code16 |
1834 |
|
1835 |
pushw %ds |
1836 |
|
1837 |
movw %dx,%ds |
1838 |
shll $4,%edx |
1839 |
|
1840 |
subw $sizeof_menu_desc,%sp |
1841 |
movw %esp,%ebp |
1842 |
|
1843 |
movl gfx_ofs_menu_entries(%bx),%eax |
1844 |
movw %ax,menu_entries(%bp) |
1845 |
|
1846 |
movl gfx_ofs_menu_default_entry(%bx),%eax |
1847 |
subl %edx,%eax |
1848 |
movw %ax,menu_default(%bp) |
1849 |
movw %ds,menu_default+2(%bp) |
1850 |
|
1851 |
movl gfx_ofs_menu_list(%bx),%eax |
1852 |
subl %edx,%eax |
1853 |
movw %ax,menu_ent_list(%bp) |
1854 |
movw %ds,menu_ent_list+2(%bp) |
1855 |
|
1856 |
movl gfx_ofs_menu_entry_len(%bx),%eax |
1857 |
movw %ax,menu_ent_size(%bp) |
1858 |
|
1859 |
movl gfx_ofs_args_list(%bx),%eax |
1860 |
subl %edx,%eax |
1861 |
movw %ax,menu_arg_list(%bp) |
1862 |
movw %ds,menu_arg_list+2(%bp) |
1863 |
|
1864 |
movl gfx_ofs_args_entry_len(%bx),%eax |
1865 |
movw %ax,menu_arg_size(%bp) |
1866 |
|
1867 |
movl %ss,%esi |
1868 |
shll $4,%esi |
1869 |
addl %ebp,%esi |
1870 |
|
1871 |
lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx) |
1872 |
|
1873 |
addw $sizeof_menu_desc,%sp |
1874 |
|
1875 |
popw %ds |
1876 |
|
1877 |
DATA32 call EXT_C(real_to_prot) |
1878 |
.code32 |
1879 |
|
1880 |
xorl %eax,%eax |
1881 |
|
1882 |
popl %ebx |
1883 |
popl %esi |
1884 |
popl %edi |
1885 |
|
1886 |
popl %ebp |
1887 |
ret |
1888 |
|
1889 |
|
1890 |
/* |
1891 |
* |
1892 |
* end graphics stuff |
1893 |
* |
1894 |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
1895 |
*/ |
1896 |
|
1617 |
|
1897 |
|
1618 |
/* |
1898 |
/* |
1619 |
* gateA20(int linear) |
1899 |
* gateA20(int linear) |
1620 |
-- stage2/builtins.c |
1900 |
++ stage2/builtins.c |
Lines 63-68
Link Here
|
63 |
int fallback_entries[MAX_FALLBACK_ENTRIES]; |
63 |
int fallback_entries[MAX_FALLBACK_ENTRIES]; |
64 |
/* The number of current entry. */ |
64 |
/* The number of current entry. */ |
65 |
int current_entryno; |
65 |
int current_entryno; |
|
|
66 |
/* graphics file */ |
67 |
char graphics_file[64]; |
66 |
/* The address for Multiboot command-line buffer. */ |
68 |
/* The address for Multiboot command-line buffer. */ |
67 |
static char *mb_cmdline; |
69 |
static char *mb_cmdline; |
68 |
/* The password. */ |
70 |
/* The password. */ |
Lines 1351-1356
Link Here
|
1351 |
}; |
1353 |
}; |
1352 |
|
1354 |
|
1353 |
|
1355 |
|
|
|
1356 |
/* graphics */ |
1357 |
static int |
1358 |
gfxmenu_func (char *arg, int flags) |
1359 |
{ |
1360 |
memmove(graphics_file, arg, sizeof graphics_file - 1); |
1361 |
graphics_file[sizeof graphics_file - 1] = 0; |
1362 |
|
1363 |
return 0; |
1364 |
} |
1365 |
|
1366 |
static struct builtin builtin_gfxmenu = |
1367 |
{ |
1368 |
"gfxmenu", |
1369 |
gfxmenu_func, |
1370 |
BUILTIN_MENU | BUILTIN_HELP_LIST, |
1371 |
"gfxmenu FILE", |
1372 |
"Use the graphical menu from FILE." |
1373 |
}; |
1374 |
|
1375 |
|
1354 |
/* geometry */ |
1376 |
/* geometry */ |
1355 |
static int |
1377 |
static int |
1356 |
geometry_func (char *arg, int flags) |
1378 |
geometry_func (char *arg, int flags) |
Lines 4874-4879
Link Here
|
4874 |
&builtin_find, |
4896 |
&builtin_find, |
4875 |
&builtin_fstest, |
4897 |
&builtin_fstest, |
4876 |
&builtin_geometry, |
4898 |
&builtin_geometry, |
|
|
4899 |
&builtin_gfxmenu, |
4877 |
&builtin_halt, |
4900 |
&builtin_halt, |
4878 |
&builtin_help, |
4901 |
&builtin_help, |
4879 |
&builtin_hiddenmenu, |
4902 |
&builtin_hiddenmenu, |
4880 |
-- stage2/shared.h |
4903 |
++ stage2/shared.h |
Lines 374-379
Link Here
|
374 |
#endif /* WITHOUT_LIBC_STUBS */ |
374 |
#endif /* WITHOUT_LIBC_STUBS */ |
375 |
|
375 |
|
376 |
|
376 |
|
|
|
377 |
/* see typedef gfx_data_t below */ |
378 |
#define gfx_ofs_ok 0x00 |
379 |
#define gfx_ofs_code_seg 0x04 |
380 |
#define gfx_ofs_jmp_table 0x08 |
381 |
#define gfx_ofs_sys_cfg 0x38 |
382 |
#define gfx_ofs_cmdline 0x6c |
383 |
#define gfx_ofs_cmdline_len 0x70 |
384 |
#define gfx_ofs_menu_list 0x74 |
385 |
#define gfx_ofs_menu_default_entry 0x78 |
386 |
#define gfx_ofs_menu_entries 0x7c |
387 |
#define gfx_ofs_menu_entry_len 0x80 |
388 |
#define gfx_ofs_args_list 0x84 |
389 |
#define gfx_ofs_args_entry_len 0x88 |
390 |
#define gfx_ofs_timeout 0x8c |
391 |
|
392 |
|
377 |
#ifndef ASM_FILE |
393 |
#ifndef ASM_FILE |
378 |
/* |
394 |
/* |
379 |
* Below this should be ONLY defines and other constructs for C code. |
395 |
* Below this should be ONLY defines and other constructs for C code. |
Lines 595-600
Link Here
|
595 |
extern int default_entry; |
611 |
extern int default_entry; |
596 |
extern int current_entryno; |
612 |
extern int current_entryno; |
597 |
|
613 |
|
|
|
614 |
|
615 |
/* |
616 |
* graphics menu stuff |
617 |
* |
618 |
* Note: gfx_data and all data referred to in it must lie within a 64k area. |
619 |
*/ |
620 |
typedef struct { |
621 |
unsigned ok; /* set while we're in graphics mode */ |
622 |
unsigned code_seg; /* code segment of binary graphics code */ |
623 |
unsigned jmp_table[12]; /* link to graphics functions */ |
624 |
unsigned char sys_cfg[52]; /* sys_cfg[0]: identifies boot loader (grub == 2) */ |
625 |
char *cmdline; /* command line returned by gfx_input() */ |
626 |
unsigned cmdline_len; /* length of the above */ |
627 |
char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */ |
628 |
char *menu_default_entry; /* the default entry */ |
629 |
unsigned menu_entries; /* number of entries in menu_list */ |
630 |
unsigned menu_entry_len; /* one entry */ |
631 |
char *args_list; /* same structure as menu_list, menu_entries entries */ |
632 |
unsigned args_entry_len; /* one entry */ |
633 |
unsigned timeout; /* in seconds (0: no timeout) */ |
634 |
} __attribute__ ((packed)) gfx_data_t; |
635 |
|
636 |
extern gfx_data_t *graphics_data; |
637 |
|
638 |
/* pointer to graphics image data */ |
639 |
extern char graphics_file[64]; |
640 |
|
641 |
int gfx_init(gfx_data_t *gfx_data); |
642 |
int gfx_done(gfx_data_t *gfx_data); |
643 |
int gfx_input(gfx_data_t *gfx_data, int *menu_entry); |
644 |
int gfx_setup_menu(gfx_data_t *gfx_data); |
645 |
|
598 |
/* The constants for password types. */ |
646 |
/* The constants for password types. */ |
599 |
typedef enum |
647 |
typedef enum |
600 |
{ |
648 |
{ |
601 |
-- stage2/stage2.c |
649 |
++ stage2/stage2.c |
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 |
/* kernel + (grub-)module options */ |
802 |
#define GFX_CMD_BUF_SIZE 512 |
803 |
|
804 |
/* command line separator char */ |
805 |
#define GFX_CMD_SEP 1 |
806 |
|
807 |
/* |
808 |
* Go through config entry and find kernel args, if any. |
809 |
* Put things into buf and return it. |
810 |
*/ |
811 |
static char *get_kernel_args(char *cfg, char *buf) |
812 |
{ |
813 |
int i, j; |
814 |
char *s, *t = "", *p, *t2; |
815 |
|
816 |
*(p = buf) = 0; |
817 |
|
818 |
for(j = 0; ; j++) { |
819 |
s = get_entry(cfg, j, 0); |
820 |
if(!*s) break; |
821 |
if( |
822 |
(!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && |
823 |
(s[6] == ' ' || s[6] == '\t') |
824 |
) { |
825 |
t = skip_to(0, s); |
826 |
t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; |
827 |
if(*t) t = skip_to(0, t); |
828 |
if(t2 && t2 < t) break; /* module is likely a normal initrd -> skip */ |
829 |
i = strlen(t); |
830 |
if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break; |
831 |
*p++ = GFX_CMD_SEP; |
832 |
strcpy(p, t); |
833 |
p += i; |
834 |
|
835 |
continue; |
836 |
} |
837 |
} |
838 |
|
839 |
if(*buf) buf++; /* skip initial separator char */ |
840 |
|
841 |
return buf; |
842 |
} |
843 |
|
844 |
|
845 |
/* |
846 |
* Check header and return code start offset. |
847 |
*/ |
848 |
static unsigned magic_ok(unsigned char *buf) |
849 |
{ |
850 |
if( |
851 |
*(unsigned *) buf == 0x0b2d97f00 && /* magic id */ |
852 |
(buf[4] == 8) /* version 8 */ |
853 |
) { |
854 |
return *(unsigned *) (buf + 8); |
855 |
} |
856 |
|
857 |
return 0; |
858 |
} |
859 |
|
860 |
|
861 |
/* |
862 |
* Search cpio archive for gfx file. |
863 |
*/ |
864 |
static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len) |
865 |
{ |
866 |
unsigned i, fname_len, code_start = 0; |
867 |
|
868 |
*gfx_file_start = 0; |
869 |
|
870 |
for(i = 0; i < len;) { |
871 |
if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) { |
872 |
fname_len = *(unsigned short *) (buf + i + 20); |
873 |
*file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16); |
874 |
i += 26 + fname_len; |
875 |
i = ((i + 1) & ~1); |
876 |
if((code_start = magic_ok(buf + i))) { |
877 |
*gfx_file_start = i; |
878 |
return code_start; |
879 |
} |
880 |
i += *file_len; |
881 |
i = ((i + 1) & ~1); |
882 |
} |
883 |
else { |
884 |
break; |
885 |
} |
886 |
} |
887 |
|
888 |
return code_start; |
889 |
} |
890 |
|
891 |
static inline unsigned char * stack_ptr(void) |
892 |
{ |
893 |
unsigned char * u; |
894 |
|
895 |
asm("movl %%esp, %0" : "=r" (u)); |
896 |
|
897 |
return u; |
898 |
} |
899 |
|
900 |
static void sleep(int delay) |
901 |
{ |
902 |
int tick, last_tick = currticks(); |
903 |
|
904 |
delay *= 18; |
905 |
|
906 |
while(delay--) { |
907 |
while((tick = currticks()) == last_tick) { } |
908 |
last_tick = tick; |
909 |
} |
910 |
} |
911 |
|
912 |
static void wait_for_key() |
913 |
{ |
914 |
printf("Press a key to continue..."); |
915 |
getkey(); |
916 |
printf("\r \r"); |
917 |
} |
918 |
|
919 |
|
920 |
/* |
921 |
* Leave that much space on the heap. Everything else goes to the graphics |
922 |
* functions. |
923 |
* |
924 |
* 0x2000 is _not_ enough |
925 |
*/ |
926 |
#define MIN_HEAP_SIZE 0x4000 |
927 |
#define MIN_GFX_FREE 0x1000 |
928 |
|
929 |
#define SC_BOOTLOADER 0 |
930 |
#define SC_FAILSAFE 3 |
931 |
#define SC_SYSCONFIG_SIZE 4 |
932 |
#define SC_BOOTLOADER_SEG 8 |
933 |
#define SC_XMEM_0 24 |
934 |
#define SC_XMEM_1 26 |
935 |
#define SC_XMEM_2 28 |
936 |
#define SC_XMEM_3 30 |
937 |
#define SC_FILE 32 |
938 |
#define SC_ARCHIVE_START 36 |
939 |
#define SC_ARCHIVE_END 40 |
940 |
#define SC_MEM0_START 44 |
941 |
#define SC_MEM0_END 48 |
942 |
|
943 |
/* |
944 |
* Does normally not return. |
945 |
*/ |
946 |
static void |
947 |
run_graphics_menu (char *menu_entries, char *config_entries, int num_entries, |
948 |
char *heap, int entryno) |
949 |
{ |
950 |
unsigned char *buf, *buf_ext; |
951 |
unsigned buf_size, buf_ext_size, code_start, file_start; |
952 |
char *s, *t, *t2, *cfg, *new_config, *p; |
953 |
char *saved_heap; |
954 |
int i, j, max_len, gfx_file_size, verbose; |
955 |
int selected_entry; |
956 |
gfx_data_t *gfx_data; |
957 |
char *cmd_buf; |
958 |
unsigned mem0_start, mem0_end, file_len; |
959 |
|
960 |
/* |
961 |
* check gfx_data_t struct offsets for consistency; gcc will optimize away |
962 |
* the whole block |
963 |
*/ |
964 |
|
965 |
/* dummy function to make ld fail */ |
966 |
{ |
967 |
extern void wrong_struct_size(void); |
968 |
#define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size(); |
969 |
gfx_ofs_check(ok); |
970 |
gfx_ofs_check(code_seg); |
971 |
gfx_ofs_check(jmp_table); |
972 |
gfx_ofs_check(sys_cfg); |
973 |
gfx_ofs_check(cmdline); |
974 |
gfx_ofs_check(cmdline_len); |
975 |
gfx_ofs_check(menu_list); |
976 |
gfx_ofs_check(menu_default_entry); |
977 |
gfx_ofs_check(menu_entries); |
978 |
gfx_ofs_check(menu_entry_len); |
979 |
gfx_ofs_check(args_list); |
980 |
gfx_ofs_check(args_entry_len); |
981 |
gfx_ofs_check(timeout); |
982 |
#undef gfx_ofs_check |
983 |
} |
984 |
|
985 |
if(!num_entries) return; |
986 |
|
987 |
graphics_data = gfx_data = (gfx_data_t *) heap; |
988 |
heap += sizeof *gfx_data; |
989 |
memset(gfx_data, 0, sizeof *gfx_data); |
990 |
|
991 |
gfx_data->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */ |
992 |
gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */ |
993 |
*(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4; /* segment */ |
994 |
gfx_data->sys_cfg[SC_XMEM_0] = 0x21; /* 1MB @ 2MB */ |
995 |
gfx_data->sys_cfg[SC_XMEM_1] = 0x41; /* 1MB @ 4MB */ |
996 |
verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */ |
997 |
gfx_data->sys_cfg[SC_FAILSAFE] = verbose; |
998 |
|
999 |
gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0; |
1000 |
|
1001 |
|
1002 |
/* setup command line edit buffer */ |
1003 |
|
1004 |
gfx_data->cmdline_len = 256; |
1005 |
|
1006 |
gfx_data->cmdline = heap; |
1007 |
heap += gfx_data->cmdline_len; |
1008 |
memset(gfx_data->cmdline, 0, gfx_data->cmdline_len); |
1009 |
|
1010 |
cmd_buf = heap; |
1011 |
heap += GFX_CMD_BUF_SIZE; |
1012 |
|
1013 |
/* setup menu entries */ |
1014 |
|
1015 |
for(i = max_len = 0; i < num_entries; i++) { |
1016 |
j = strlen(get_entry(menu_entries, i, 0)); |
1017 |
if(j > max_len) max_len = j; |
1018 |
} |
1019 |
|
1020 |
if(!max_len) return; |
1021 |
|
1022 |
gfx_data->menu_entry_len = max_len + 1; |
1023 |
gfx_data->menu_entries = num_entries; |
1024 |
|
1025 |
gfx_data->menu_list = heap; |
1026 |
heap += gfx_data->menu_entry_len * gfx_data->menu_entries; |
1027 |
|
1028 |
memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries); |
1029 |
|
1030 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
1031 |
strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0)); |
1032 |
} |
1033 |
|
1034 |
gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len; |
1035 |
|
1036 |
|
1037 |
/* setup list of kernel args */ |
1038 |
|
1039 |
for(i = max_len = 0; i < num_entries; i++) { |
1040 |
s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf); |
1041 |
j = strlen(s); |
1042 |
if(j > max_len) max_len = j; |
1043 |
} |
1044 |
|
1045 |
gfx_data->args_entry_len = max_len + 1; |
1046 |
|
1047 |
gfx_data->args_list = heap; |
1048 |
heap += gfx_data->args_entry_len * gfx_data->menu_entries; |
1049 |
|
1050 |
memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries); |
1051 |
|
1052 |
for(i = 0; i < (int) gfx_data->menu_entries; i++) { |
1053 |
strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf)); |
1054 |
} |
1055 |
|
1056 |
|
1057 |
/* go back here when we no longer need the graphics data */ |
1058 |
saved_heap = heap; |
1059 |
|
1060 |
|
1061 |
/* get memory area to be used by graphics functions */ |
1062 |
|
1063 |
/* use 1MB starting at 2MB as file buffer */ |
1064 |
buf_ext = (unsigned char *) (2 << 20); |
1065 |
buf_ext_size = 1 << 20; |
1066 |
|
1067 |
/* must be 16-byte aligned */ |
1068 |
buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); |
1069 |
|
1070 |
buf_size = stack_ptr() - buf - MIN_HEAP_SIZE; |
1071 |
buf_size &= ~0xf; |
1072 |
|
1073 |
mem0_start = (unsigned) buf; |
1074 |
mem0_end = mem0_start + buf_size; |
1075 |
|
1076 |
if(verbose) { |
1077 |
printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size); |
1078 |
wait_for_key(); |
1079 |
} |
1080 |
|
1081 |
heap += buf_size; |
1082 |
|
1083 |
/* read the file */ |
1084 |
|
1085 |
if(!grub_open(graphics_file)) { |
1086 |
printf("%s: file not found\n", graphics_file); |
1087 |
sleep(5); |
1088 |
heap = saved_heap; |
1089 |
return; |
1090 |
} |
1091 |
|
1092 |
gfx_file_size = grub_read(buf_ext, buf_ext_size); |
1093 |
|
1094 |
grub_close(); |
1095 |
|
1096 |
if(gfx_file_size <= 0) { |
1097 |
printf("%s: read error\n", graphics_file); |
1098 |
sleep(5); |
1099 |
heap = saved_heap; |
1100 |
return; |
1101 |
} |
1102 |
|
1103 |
if(verbose) { |
1104 |
printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size); |
1105 |
wait_for_key(); |
1106 |
} |
1107 |
|
1108 |
/* locate file inside cpio archive */ |
1109 |
if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) { |
1110 |
printf("%s: invalid file format\n", graphics_file); |
1111 |
sleep(5); |
1112 |
heap = saved_heap; |
1113 |
return; |
1114 |
} |
1115 |
|
1116 |
if(verbose) { |
1117 |
printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start); |
1118 |
wait_for_key(); |
1119 |
} |
1120 |
|
1121 |
if(file_len - code_start + MIN_GFX_FREE > buf_size) { |
1122 |
printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size); |
1123 |
sleep(5); |
1124 |
heap = saved_heap; |
1125 |
return; |
1126 |
} |
1127 |
|
1128 |
memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start); |
1129 |
|
1130 |
mem0_start += file_len - code_start; |
1131 |
mem0_start = (mem0_start + 3) & ~3; /* align */ |
1132 |
|
1133 |
/* init interface to graphics functions */ |
1134 |
|
1135 |
*(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start; |
1136 |
*(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext; |
1137 |
*(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size; |
1138 |
*(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start; |
1139 |
*(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end; |
1140 |
|
1141 |
gfx_data->code_seg = (unsigned) buf >> 4; |
1142 |
|
1143 |
if(verbose) { |
1144 |
printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n", |
1145 |
(unsigned) buf_ext + file_start, |
1146 |
(unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size, |
1147 |
mem0_start, mem0_end, gfx_data->code_seg |
1148 |
); |
1149 |
wait_for_key(); |
1150 |
} |
1151 |
|
1152 |
for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) { |
1153 |
gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i]; |
1154 |
} |
1155 |
|
1156 |
if(verbose) { |
1157 |
for(i = 0; i < 12; i++) { |
1158 |
printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]); |
1159 |
} |
1160 |
|
1161 |
for(i = 0; i < gfx_data->menu_entries; i++) { |
1162 |
printf("\"%s\" -- \"%s\"\n", |
1163 |
gfx_data->menu_list + i * gfx_data->menu_entry_len, |
1164 |
gfx_data->args_list + i * gfx_data->args_entry_len |
1165 |
); |
1166 |
} |
1167 |
|
1168 |
printf("default: \"%s\"\n", gfx_data->menu_default_entry); |
1169 |
wait_for_key(); |
1170 |
} |
1171 |
|
1172 |
/* switch to graphics mode */ |
1173 |
|
1174 |
if(gfx_init(gfx_data)) { |
1175 |
printf("graphics initialization failed\n"); |
1176 |
sleep(5); |
1177 |
heap = saved_heap; |
1178 |
return; |
1179 |
} |
1180 |
|
1181 |
gfx_setup_menu(gfx_data); |
1182 |
|
1183 |
i = gfx_input(gfx_data, &selected_entry); |
1184 |
|
1185 |
/* ESC -> show text menu */ |
1186 |
if(i == 1) { |
1187 |
gfx_done(gfx_data); |
1188 |
grub_timeout = -1; |
1189 |
|
1190 |
heap = saved_heap; |
1191 |
return; |
1192 |
} |
1193 |
|
1194 |
gfx_done(gfx_data); |
1195 |
|
1196 |
heap = saved_heap; /* free most of the graphics data */ |
1197 |
|
1198 |
// printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry); |
1199 |
|
1200 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1201 |
|
1202 |
|
1203 |
/* create new config with modified kernel option */ |
1204 |
|
1205 |
cfg = get_entry(config_entries, selected_entry, 1); |
1206 |
|
1207 |
new_config = heap; |
1208 |
|
1209 |
for(p = gfx_data->cmdline, i = 0; ; i++) { |
1210 |
s = get_entry(cfg, i, 0); |
1211 |
if(!*s) { |
1212 |
if(!i) *heap++ = 0; |
1213 |
*heap++ = 0; |
1214 |
break; |
1215 |
} |
1216 |
/* note: must match get_kernel_args() */ |
1217 |
if( |
1218 |
(!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) && |
1219 |
(s[6] == ' ' || s[6] == '\t') |
1220 |
) { |
1221 |
t = skip_to(0, s); |
1222 |
t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL; |
1223 |
if(*t) t = skip_to(0, t); |
1224 |
if(t2 && t2 < t) { /* module is likely a normal initrd -> skip */ |
1225 |
strcpy(heap, s); |
1226 |
heap += strlen(s) + 1; |
1227 |
continue; |
1228 |
} |
1229 |
memmove(heap, s, t - s); |
1230 |
heap += t - s; |
1231 |
*heap++ = ' '; |
1232 |
while(*p && *p != GFX_CMD_SEP) *heap++ = *p++; |
1233 |
*heap++ = 0; |
1234 |
if(*p == GFX_CMD_SEP) p++; |
1235 |
} |
1236 |
else { |
1237 |
strcpy(heap, s); |
1238 |
heap += strlen(s) + 1; |
1239 |
} |
1240 |
} |
1241 |
|
1242 |
*heap++ = 0; |
1243 |
|
1244 |
// hexdump(new_config, heap - new_config); |
1245 |
// getkey(); |
1246 |
|
1247 |
run_script(new_config, heap); |
1248 |
} |
1249 |
|
1250 |
|
756 |
static int |
1251 |
static int |
757 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
1252 |
get_line_from_config (char *cmdline, int maxlen, int read_from_file) |
758 |
{ |
1253 |
{ |
Lines 1062-1070
Link Here
|
1062 |
} |
1557 |
} |
1063 |
else |
1558 |
else |
1064 |
{ |
1559 |
{ |
1065 |
/* Run menu interface. */ |
1560 |
if (*graphics_file && !password && show_menu && grub_timeout) |
1066 |
run_menu (menu_entries, config_entries, num_entries, |
1561 |
{ |
1067 |
menu_entries + menu_len, default_entry); |
1562 |
run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry); |
|
|
1563 |
} |
1564 |
/* Run menu interface. */ |
1565 |
run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); |
1068 |
} |
1566 |
} |
1069 |
} |
1567 |
} |
1070 |
} |
1568 |
} |
1071 |
-- stage2/stage2.c |
1569 |
++ stage2/stage2.c |
Lines 1199-1204
Link Here
|
1199 |
|
1199 |
|
1200 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1200 |
if(selected_entry < 0 || selected_entry > num_entries) return; |
1201 |
|
1201 |
|
|
|
1202 |
/* for 'savedefault' */ |
1203 |
current_entryno = selected_entry; |
1204 |
|
1202 |
|
1205 |
|
1203 |
/* create new config with modified kernel option */ |
1206 |
/* create new config with modified kernel option */ |
1204 |
|
1207 |
|