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:
okuji committed 1999-07-12 00:47:11 +00:00
1 parent d66583f802
commit cb7e6d5e4e
11 files changed
+655 -139

No files matched your search

+4 -5
View File
@@ -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;
}
}
+38
View File
@@ -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
View File
@@ -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
View File
@@ -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);