mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-21 14:59:34 +00:00
Bug fixes in the geometry detection. Linux video mode selection support. New Stage 1 stage1_lba is added. Stage 1.5 becomes much smaller.
This commit is contained in:
1 parent
d66583f802
commit
cb7e6d5e4e
11 files changed
+655
-139
No files matched your search
+4
-5
@@ -118,6 +118,9 @@ int
|
||||
get_diskinfo (int drive, struct geometry *geometry)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Clear the flags. */
|
||||
geometry->flags = 0;
|
||||
|
||||
if (drive & 0x80)
|
||||
{
|
||||
@@ -159,11 +162,7 @@ get_diskinfo (int drive, struct geometry *geometry)
|
||||
|
||||
/* Check if CHS information is valid. */
|
||||
if (drp.flags & 0x02)
|
||||
{
|
||||
total_sectors = (geometry->cylinders
|
||||
* geometry->heads
|
||||
* geometry->sectors);
|
||||
}
|
||||
total_sectors = drp.cylinders * drp.heads * drp.sectors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,6 +198,44 @@ load_image (void)
|
||||
|
||||
if (mbi.mem_lower >= 608)
|
||||
{
|
||||
/* Video mode selection support. What a shit! */
|
||||
{
|
||||
char *vga;
|
||||
|
||||
/* Find the substring "vga=". */
|
||||
vga = grub_strstr (cur_cmdline, "vga=");
|
||||
if (vga)
|
||||
{
|
||||
char *value = vga + 4;
|
||||
char *vga_end;
|
||||
int vid_mode;
|
||||
|
||||
/* Handle special strings. */
|
||||
if (substring ("normal", value) < 1)
|
||||
vid_mode = LINUX_VID_MODE_NORMAL;
|
||||
else if (substring ("ext", value) < 1)
|
||||
vid_mode = LINUX_VID_MODE_EXTENDED;
|
||||
else if (substring ("ask", value) < 1)
|
||||
vid_mode = LINUX_VID_MODE_ASK;
|
||||
else if (safe_parse_maxint (&value, &vid_mode))
|
||||
;
|
||||
else
|
||||
/* ERRNUM is already set inside the function
|
||||
safe_parse_maxint. */
|
||||
return 0;
|
||||
|
||||
/* Set the vid mode to VID_MODE. Note that this can work
|
||||
because i386 architecture is little-endian. */
|
||||
grub_memmove (buffer + LINUX_VID_MODE_OFFSET,
|
||||
(char *) &vid_mode,
|
||||
sizeof (unsigned short));
|
||||
|
||||
/* Remove the "vga=...". */
|
||||
vga_end = skip_to (0, vga);
|
||||
grub_memmove (vga, vga_end, grub_strlen (vga_end));
|
||||
}
|
||||
}
|
||||
|
||||
memmove ((char *) LINUX_SETUP, buffer, data_len + SECTOR_SIZE);
|
||||
|
||||
/* copy command-line plus memory hack to staging area */
|
||||
|
||||
+63
-54
@@ -31,7 +31,7 @@ print_error (void)
|
||||
/* printf("\7\n %s\n", err_list[errnum]); */
|
||||
printf ("\n %s\n", err_list[errnum]);
|
||||
#else /* STAGE1_5 */
|
||||
printf ("Error: %d\n", errnum);
|
||||
printf ("Error: %u\n", errnum);
|
||||
#endif /* STAGE1_5 */
|
||||
|
||||
errnum = ERR_NONE;
|
||||
@@ -44,6 +44,7 @@ convert_to_ascii (char *buf, int c,...)
|
||||
unsigned long num = *((&c) + 1), mult = 10;
|
||||
char *ptr = buf;
|
||||
|
||||
#ifndef STAGE1_5
|
||||
if (c == 'x')
|
||||
mult = 16;
|
||||
|
||||
@@ -53,6 +54,7 @@ convert_to_ascii (char *buf, int c,...)
|
||||
*(ptr++) = '-';
|
||||
buf++;
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
@@ -80,7 +82,7 @@ convert_to_ascii (char *buf, int c,...)
|
||||
|
||||
|
||||
void
|
||||
grub_printf (char *format,...)
|
||||
grub_printf (const char *format,...)
|
||||
{
|
||||
int *dataptr = (int *) &format;
|
||||
char c, *ptr, str[16];
|
||||
@@ -94,9 +96,11 @@ grub_printf (char *format,...)
|
||||
else
|
||||
switch (c = *(format++))
|
||||
{
|
||||
#ifndef STAGE1_5
|
||||
case 'd':
|
||||
case 'u':
|
||||
case 'x':
|
||||
#endif
|
||||
case 'u':
|
||||
*convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
|
||||
|
||||
ptr = str;
|
||||
@@ -422,39 +426,11 @@ get_cmdline (char *prompt, char *commands, char *cmdline, int maxlen,
|
||||
#endif /* STAGE1_5 */
|
||||
|
||||
|
||||
int
|
||||
get_based_digit (int c, int base)
|
||||
{
|
||||
int digit = -1;
|
||||
|
||||
/* make sure letter in the the range we can check! */
|
||||
c = tolower (c);
|
||||
|
||||
/*
|
||||
* Is it in the range between zero and nine?
|
||||
*/
|
||||
if (base > 0 && c >= '0' && c <= '9' && c < (base + '0'))
|
||||
{
|
||||
digit = c - '0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Is it in the range used by a letter?
|
||||
*/
|
||||
if (base > 10 && c >= 'a' && c <= 'z' && c < ((base - 10) + 'a'))
|
||||
{
|
||||
digit = c - 'a' + 10;
|
||||
}
|
||||
|
||||
return digit;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
safe_parse_maxint (char **str_ptr, int *myint_ptr)
|
||||
{
|
||||
register char *ptr = *str_ptr;
|
||||
register int myint = 0, digit;
|
||||
char *ptr = *str_ptr;
|
||||
int myint = 0;
|
||||
int mult = 10, found = 0;
|
||||
|
||||
/*
|
||||
@@ -466,8 +442,22 @@ safe_parse_maxint (char **str_ptr, int *myint_ptr)
|
||||
mult = 16;
|
||||
}
|
||||
|
||||
while ((digit = get_based_digit (*ptr, mult)) != -1)
|
||||
while (1)
|
||||
{
|
||||
/* A bit tricky. This below makes use of the equivalence:
|
||||
(A >= B && A <= C) <=> ((A - B) <= (C - B))
|
||||
when C > B and A is unsigned. */
|
||||
unsigned int digit;
|
||||
|
||||
digit = tolower (*ptr) - '0';
|
||||
if (digit > 9)
|
||||
{
|
||||
digit -= 'a' - '0';
|
||||
if (mult == 10 || digit > 5)
|
||||
break;
|
||||
digit += 10;
|
||||
}
|
||||
|
||||
found = 1;
|
||||
if (myint > ((MAXINT - digit) / mult))
|
||||
{
|
||||
@@ -513,7 +503,7 @@ grub_isspace (int c)
|
||||
|
||||
#ifndef STAGE1_5
|
||||
int
|
||||
grub_strncat (char *s1, char *s2, int n)
|
||||
grub_strncat (char *s1, const char *s2, int n)
|
||||
{
|
||||
int i = -1;
|
||||
|
||||
@@ -533,7 +523,7 @@ grub_strncat (char *s1, char *s2, int n)
|
||||
|
||||
|
||||
int
|
||||
grub_strcmp (char *s1, char *s2)
|
||||
grub_strcmp (const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 || *s2)
|
||||
{
|
||||
@@ -571,9 +561,9 @@ substring (char *s1, char *s2)
|
||||
|
||||
#ifndef STAGE1_5
|
||||
char *
|
||||
grub_strstr (char *s1, char *s2)
|
||||
grub_strstr (const char *s1, const char *s2)
|
||||
{
|
||||
char *ptr, *tmp;
|
||||
const char *ptr, *tmp;
|
||||
|
||||
while (*s1)
|
||||
{
|
||||
@@ -583,11 +573,22 @@ grub_strstr (char *s1, char *s2)
|
||||
while (*s1 && *s1++ == *tmp++);
|
||||
|
||||
if (tmp > s2 && !*(tmp - 1))
|
||||
return ptr;
|
||||
return (char *) ptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
grub_strlen (const char *str)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
while (*str++)
|
||||
len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
#endif /* ! STAGE1_5 */
|
||||
|
||||
|
||||
@@ -616,31 +617,39 @@ memcheck (int start, int len)
|
||||
|
||||
|
||||
char *
|
||||
grub_memmove (char *to, char *from, int len)
|
||||
grub_memmove (char *to, const char *from, int len)
|
||||
{
|
||||
char *ret = to;
|
||||
if (memcheck ((int) to, len))
|
||||
{
|
||||
if ((to >= from + len) || (to <= from))
|
||||
/* This assembly code is stolen from
|
||||
linux-2.2.2/include/asm-i386/string.h. This is not very fast
|
||||
but compact. */
|
||||
int d0, d1, d2;
|
||||
|
||||
if (to < from)
|
||||
{
|
||||
while (len >= sizeof (unsigned long))
|
||||
{
|
||||
len -= sizeof (unsigned long);
|
||||
*(((unsigned long *) to)++) = *(((unsigned long *) from)++);
|
||||
}
|
||||
while (len-- > 0)
|
||||
*(to++) = *(from++);
|
||||
asm volatile ("cld\n\t"
|
||||
"rep\n\t"
|
||||
"movsb"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
: "0" (len),"1" (from),"2" (to)
|
||||
: "memory");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have a region that overlaps, but would be overwritten
|
||||
if we copied it forward. */
|
||||
while (len-- > 0)
|
||||
to[len] = from[len];
|
||||
asm volatile ("std\n\t"
|
||||
"rep\n\t"
|
||||
"movsb\n\t"
|
||||
"cld"
|
||||
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
|
||||
: "0" (len),
|
||||
"1" (len - 1 + from),
|
||||
"2" (len - 1 + to)
|
||||
: "memory");
|
||||
}
|
||||
}
|
||||
|
||||
return errnum ? NULL : ret;
|
||||
return errnum ? NULL : to;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+13
-5
@@ -89,6 +89,12 @@ extern char *grub_scratch_mem;
|
||||
#define LINUX_SETUP_CODE_START 0x214
|
||||
#define LINUX_SETUP_INITRD 0x218
|
||||
|
||||
/* Linux's video mode selection support. Actually I hate it! */
|
||||
#define LINUX_VID_MODE_OFFSET 0x1FA
|
||||
#define LINUX_VID_MODE_NORMAL 0xFFFF
|
||||
#define LINUX_VID_MODE_EXTENDED 0xFFFE
|
||||
#define LINUX_VID_MODE_ASK 0xFFFD
|
||||
|
||||
#define CL_MY_LOCATION RAW_ADDR (0x92000)
|
||||
#define CL_MY_END_ADDR RAW_ADDR (0x920FF)
|
||||
#define CL_MAGIC_ADDR RAW_ADDR (0x90020)
|
||||
@@ -235,6 +241,7 @@ extern char *grub_scratch_mem;
|
||||
#define strstr grub_strstr
|
||||
#define strcmp grub_strcmp
|
||||
#define tolower grub_tolower
|
||||
#define strlen grub_strlen
|
||||
#endif /* WITHOUT_LIBC_STUBS */
|
||||
|
||||
|
||||
@@ -503,14 +510,15 @@ cmdline_t enter_cmdline (char *script, char *heap);
|
||||
#endif
|
||||
|
||||
/* C library replacement functions with identical semantics. */
|
||||
void grub_printf (char *format,...);
|
||||
void grub_printf (const char *format,...);
|
||||
int grub_tolower (int c);
|
||||
int grub_isspace (int c);
|
||||
int grub_strncat (char *s1, char *s2, int n);
|
||||
char *grub_memmove (char *to, char *from, int len);
|
||||
int grub_strncat (char *s1, const char *s2, int n);
|
||||
char *grub_memmove (char *to, const char *from, int len);
|
||||
void *grub_memset (void *start, int c, int len);
|
||||
char *grub_strstr (char *s1, char *s2);
|
||||
int grub_strcmp (char *s1, char *s2);
|
||||
char *grub_strstr (const char *s1, const char *s2);
|
||||
int grub_strcmp (const char *s1, const char *s2);
|
||||
int grub_strlen (const char *str);
|
||||
|
||||
/* misc */
|
||||
void init_page (void);
|
||||
|
||||
Reference in new issue
Block a user