[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: "partnew" Command Writes Wrong Ending Cylinder in MPT- adrian15 Feb
From: |
sburtchin |
Subject: |
Re: "partnew" Command Writes Wrong Ending Cylinder in MPT- adrian15 Feb 1, 2007; 6:37am |
Date: |
Thu, 15 Feb 2007 19:35:04 -0800 (PST) |
NOTE: Adding message of adrian15 Feb 1, 2007; 6:37am to Nabble thread.
Steve Burtchin escribió:
>> I can build a SGD cdrom with the changes if you want to and you can try
>> yourself to see if it works ok or not.
> That would be ideal!
See the attached cdrom once in English cdrom press 'c' key and you'll
get a grub console from which you can run the new command:
partnewbeta
I've also attached the builtins.c file so that you search for the
partnewbeta string and see what you need to add a new command.
>
>> About the bug do you think that if we write:
>>
>> if (cylinder >= buf_geom.cylinders)
>> cylinder = buf_geom.cylinders - 1;
>>
>> like this:
>> // cylinders correction
>> buf_geom.cylinders+=2;
>> if (cylinder >= buf_geom.cylinders)
>> cylinder = buf_geom.cylinders - 1;
>>
>> we will fix the bug?
>>
>> adrian15
>>
> That would definitely provide a workaround to the bug on MY COMPUTER (for
> the "partnew" command) provided "buf_geom.cylinders" is not used anywhere
> else (I don't think that it is, but its value may be). "Fix" is a
> stronger
> word implying that "buf_geom.cylinders" would be assigned the correct
> value
> to begin with. I still have'nt figured out how that gets assigned, or if
> its value gets used anywhere else that matters.
> The data in the "buf_geom"
> structure seems to get passed around quite a bit (eg. the "geometry"
> function reports 1021 cylinders also [here its the value of
> "geom.cylinders"], if that matters?).
Do you mean geom.cylinders instead of buf_geom.cylinders ... interesting.
>
> I suspect the source of the bug was a 'dirty' fix to some earlier bug. A
> safer approach might be:
>
>
> int cylinder, head, sector, bufgeomcylinders;
>
> bufgeomcylinders = buf_geom.cylinders
> bufgeomcylinders+=2;
> if (cylinder >= bufgeomcylinders)
> cylinder = bufgeomcylinders - 1;
That's the patch that I have applied.
>
>
> leaving the "buf_geom" structure unchanged, and avoiding the potential of
> awakening that earlier bug.
I do not agree with you but you may be right so I've applied your patch.
You'll tell me if you have any problem.
adrian15
--------------------------------------------------------------------------------
/* builtins.c - the GRUB builtin commands */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation,
Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Include stdio.h before shared.h, because we can't define
WITHOUT_LIBC_STUBS here. */
#ifdef GRUB_UTIL
# include <stdio.h>
#endif
#include <shared.h>
#include <filesys.h>
#include <term.h>
#ifdef SUPPORT_NETBOOT
# define GRUB 1
# include <etherboot.h>
#endif
#ifdef SUPPORT_SERIAL
# include <serial.h>
# include <terminfo.h>
#endif
#ifdef GRUB_UTIL
# include <device.h>
#else /* ! GRUB_UTIL */
# include <apic.h>
# include <smp-imps.h>
#endif /* ! GRUB_UTIL */
#ifdef USE_MD5_PASSWORDS
# include <md5.h>
#endif
#define PART_TYPE_NUMBER 18
#define PART_DESCRIPTION_MAXIMUM 44
struct partition_type
{
int id;
char *name;
};
struct partition_type partition_type_table[PART_TYPE_NUMBER] =
{
{ 1 , "FAT12"}, // 1
{ 6 , "FAT16"}, // 2
{ 7 , "HPFS/NTFS"}, // 3
{ 11 , "W95 FAT32"},// 4
{ 12 , "W95 FAT32 (LBA)"},// 5
{ 14 , "W95 FAT16 (LBA)"}, // 6
{ 15 , "W95 Ext'd (LBA)"}, // 7
{27 , "Hidden W95 FAT32"}, // 8
{28 , "Hidden W95 FAT32"}, // 9
{99 , "GNU HURD or Sys"}, // 10
{129 , "Minix / old Lin"}, // 11
{130 , "SWAP"}, // 12
{131 , "Linux"}, // 13
{134 , "NTFS volume set"}, //14
{135 , "NTFS volume set"}, //15
{136 , "Linux plaintext"},//16
{142 , "Linux LVM"}, //17
{191 , "Solaris"} //18
};
int partition_string_set (int *part_type, char *string) {
int count;
for (count=0;count<(PART_TYPE_NUMBER-1);count++) {
if (*(part_type)==partition_type_table[count].id)
{
grub_sprintf(string,"%s",partition_type_table[count].name);
return 0;
}
}
return 1;
}
void set_partition_type (char *temp_string_ptr, int *type) {
int read_char_number = 0;
char read_char;
open_device();
errnum = ERR_NONE; // We do not want that partition error makes memmove work
bad
grub_sprintf (temp_string_ptr,"%s", fsys_table[fsys_type].name);
if (fsys_type == NUM_FSYS) // We go to a fixed partition type table
{
if (partition_string_set (type, temp_string_ptr))
{grub_sprintf(temp_string_ptr,"Unknown");}
}
}
void set_partition_os (char *temp_string_ptr, int *type) {
int read_char_number = 0;
char read_char;
open_device();
errnum = ERR_NONE; // We do not want that partition error makes memmove work
bad
set_partition_type (temp_string_ptr,type);
if (!(grub_strcmp(temp_string_ptr,"fat")) ||
(!(grub_strcmp(temp_string_ptr,"HPFS/NTFS")))) {
grub_sprintf(temp_string_ptr,"WINDOWS");
} else {
*temp_string_ptr=0;
// Distro name code
if (grub_open("/etc/issue")) {
errnum = ERR_NONE; // We do not want that partition error makes memmove work
bad
while ((grub_read(&read_char, 1)) && (grub_strlen(temp_string_ptr) <
(PART_DESCRIPTION_MAXIMUM-1) )) {
errnum = ERR_NONE; // We do not want that partition error makes memmove
work bad
if ((isspace (read_char) || (read_char >= ' ' && read_char <= '~')) &&
(read_char != 10)) {
grub_sprintf(temp_string_ptr,"%s%c",temp_string_ptr,read_char);
}
read_char_number++;
}
grub_close();
} else {
errnum = ERR_NONE; // Force to open a new file
if (grub_open("/grub/stage1")) {
grub_close();
errnum = ERR_NONE;
grub_sprintf(temp_string_ptr,"%s","/BOOT");
}}
}
errnum = ERR_NONE; // Ignore any error. There should not be any.
}
void add_choose_title (void) {
add_title (&menu_array[menu_level], "$(choose_title)");
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "pause
Nothing to do");
close_title ((char *) MENU_BUF, &menu_array[menu_level]);
}
void add_part_title (void) {
add_title (&menu_array[menu_level], "N IDE SCSI GRUB HURD TYPE
OS");
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "pause
Nothing to do");
close_title ((char *) MENU_BUF, &menu_array[menu_level]);
}
void add_part_instructions (int *type, int part) {
char part_type_str_buffer[15];
char os_type_str_buffer[50];
char *part_type_str_ptr=part_type_str_buffer;
int bsd_part = (part >> 8) & 0xFF;
int pc_slice = part >> 16;
set_partition_type (part_type_str_ptr,type);
set_partition_os (os_type_str_buffer,type);
if (bsd_part == 0xFF)
{
add_title (&menu_array[menu_level], "%d hd%c%d sd%c%d (hd%d,%d) hd%ds%d %s
%s",pc_slice+1,'a' + current_drive - 0x80,pc_slice+1,'a' + current_drive -
0x80,pc_slice+1,current_drive - 0x80,pc_slice,current_drive -
0x80,pc_slice+1,part_type_str_ptr,os_type_str_buffer);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_device=(hd%d,%d)",current_drive - 0x80,pc_slice);
}
else {
add_title (&menu_array[menu_level], "%d hd%c%d sd%c%d (hd%d,%d,%c) hd%ds%d
%s %s",pc_slice+1,'a' + current_drive - 0x80,pc_slice+1,'a' + current_drive
- 0x80,pc_slice+1,current_drive - 0x80,pc_slice,bsd_part + 'a',current_drive
- 0x80,pc_slice+1,part_type_str_ptr,os_type_str_buffer);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_device=(hd%d,%d,%c)",current_drive - 0x80,pc_slice,bsd_part + 'a');
}
// Common instructions to partitions and slices
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_hurd_hd=hd%d",current_drive - 0x80);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_hd=hd%d",current_drive - 0x80);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_linux_letter=%c",'a'+current_drive - 0x80);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_lide_hd=hd%c",'a' + current_drive - 0x80);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_lscsi_hd=sd%c",'a' + current_drive - 0x80);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_part=($(out_hurd_hd),%d)",pc_slice);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_lide_part=$(out_lide_hd)%d",(pc_slice+1));
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_lscsi_part=$(out_lscsi_hd)%d",(pc_slice+1));
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_hurd_part=$(out_hurd_hd)s%d",pc_slice+1);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_linux_part=$(out_linux_letter)%d",(pc_slice+1));
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_part_n=%d",pc_slice);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_linux_end=%c%d",'a' + current_drive - 0x80, pc_slice + 1);
}
// Warning Grub logical. 0 means success
//
int there_is_a_hard_disk (void) {
int i,disk_no,j;
// Check if there's any hard disk before doing anything - Begin
for (i = 1;i < 2; i++) { for (j = 0; j < 16; j++) {
struct geometry geom;
disk_no = (i * 0x80) + j;
if (! get_diskinfo (disk_no, &geom))
return 0;
} }
return 1; //No hard disk found
}
/* The type of kernel loaded. */
kernel_t kernel_type;
/* The boot device. */
static int bootdev;
/* True when the debug mode is turned on, and false
when it is turned off. */
int debug = 0;
/* The default entry. */
int default_entry = 0;
/* The fallback entry. */
int fallback_entryno;
int fallback_entries[MAX_FALLBACK_ENTRIES];
/* The number of current entry. */
int current_entryno;
/* graphics file */
char graphics_file[64];
/* The address for Multiboot command-line buffer. */
static char *mb_cmdline;
/* The password. */
char *password;
/* The password type. */
password_t password_type;
/* The flag for indicating that the user is authoritative. */
int auth = 0;
/* The timeout. */
int grub_timeout = -1;
/* Whether to show the menu or not. */
int show_menu = 1;
/* The BIOS drive map. */
static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
int real_map_func (unsigned long to, unsigned long from) {
int i;
/* Search for an empty slot in BIOS_DRIVE_MAP. */
for (i = 0; i < DRIVE_MAP_SIZE; i++)
{
/* Perhaps the user wants to override the map. */
if ((bios_drive_map[i] & 0xff) == from)
break;
if (! bios_drive_map[i])
break;
}
if (i == DRIVE_MAP_SIZE)
{
errnum = ERR_WONT_FIT;
return 1;
}
if (to == from)
/* If TO is equal to FROM, delete the entry. */
grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i +
1],
sizeof (unsigned short) * (DRIVE_MAP_SIZE - i));
else
bios_drive_map[i] = from | (to << 8);
return 0;
}
/* Prototypes for allowing straightfoward calling of builtins functions
inside other functions. */
static int configfile_func (char *arg, int flags);
static int real_root_func (char *arg, int flags);
static int set_func (char *arg, int flags);
/* Initialize the data for builtins. */
void
init_builtins (void)
{
kernel_type = KERNEL_TYPE_NONE;
/* BSD and chainloading evil hacks! */
bootdev = set_bootdev (0);
mb_cmdline = (char *) MB_CMDLINE_BUF;
}
/* Initialize the data for the configuration file. */
void
init_config (void)
{
default_entry = 0;
password = 0;
fallback_entryno = -1;
fallback_entries[0] = -1;
grub_timeout = -1;
}
void
configfile_end (void)
{
#ifdef GRUB_UTIL
/* Force to load the configuration file. */
use_config_file = 1;
#endif
/* Make sure that the user will not be authoritative. */
auth = 0;
/* Restart cmain. */
grub_longjmp (restart_env, 0);
}
/* Check a password for correctness. Returns 0 if password was
correct, and a value != 0 for error, similarly to strcmp. */
int
check_password (char *entered, char* expected, password_t type)
{
switch (type)
{
case PASSWORD_PLAIN:
return strcmp (entered, expected);
#ifdef USE_MD5_PASSWORDS
case PASSWORD_MD5:
return check_md5_password (entered, expected);
#endif
default:
/* unsupported password type: be secure */
return 1;
}
}
/* Print which sector is read when loading a file. */
static void
disk_read_print_func (int sector, int offset, int length)
{
grub_printf ("[%d,%d,%d]", sector, offset, length);
}
/* configfile */
static int
back_func (char *arg, int flags)
{
if (menu_level>0)
{ special_menu=0; // Restore special menu to a normal one
// Go down a level
menu_level--;
return 0;
}
else
{
errnum = ERR_BAD_ARGUMENT; return 1;
}
}
static struct builtin builtin_back =
{
"back",
back_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"back FILE",
"Comes back to previously loaded menu."
};
void check_int13_handler (int modify_saved_drive) {
/* Check if we should set the int13 handler. */
if (bios_drive_map[0] != 0)
{
int i;
if (modify_saved_drive) {
/* Search for SAVED_DRIVE. */
for (i = 0; i < DRIVE_MAP_SIZE; i++)
{
if (! bios_drive_map[i])
break;
else if ((bios_drive_map[i] & 0xFF) == saved_drive)
{
/* Exchage SAVED_DRIVE with the mapped drive. */
saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
break;
}
}
}
/* Set the handler. This is somewhat dangerous. */
set_int13_handler (bios_drive_map);
}
}
/* boot */
static int
boot_func (char *arg, int flags)
{
/* Clear the int15 handler if we can boot the kernel successfully.
This assumes that the boot code never fails only if KERNEL_TYPE is
not KERNEL_TYPE_NONE. Is this assumption is bad? */
if (kernel_type != KERNEL_TYPE_NONE)
unset_int15_handler ();
#ifdef SUPPORT_NETBOOT
/* Shut down the networking. */
cleanup_net ();
#endif
switch (kernel_type)
{
case KERNEL_TYPE_FREEBSD:
case KERNEL_TYPE_NETBSD:
/* *BSD */
bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
break;
case KERNEL_TYPE_LINUX:
/* Linux */
linux_boot ();
break;
case KERNEL_TYPE_BIG_LINUX:
/* Big Linux */
big_linux_boot ();
break;
case KERNEL_TYPE_CHAINLOADER:
/* Chainloader */
/* Check if we should set the int13 handler. */
check_int13_handler(1); // 1 means that we want the function to modify
the saved drive
gateA20 (0);
boot_drive = saved_drive;
chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
break;
case KERNEL_TYPE_MULTIBOOT:
/* Multiboot */
multi_boot ((int) entry_addr, (int) &mbi);
break;
default:
errnum = ERR_BOOT_COMMAND;
return 1;
}
return 0;
}
static struct builtin builtin_boot =
{
"boot",
boot_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"boot",
"Boot the OS/chain-loader which has been loaded."
};
/* call */
static int
call_func (char *arg, int flags)
{
// NEXT CODE IS EQUIVALENT TO CONFIGFILE command
char *new_config = config_file;
/* Check if the file ARG is present. */
if (! grub_open (arg))
return 1;
grub_close ();
if(add_menu ()) return 1;
close_menu ((char *) MENU_BUF, &menu_array[menu_level]);
// Copy ARG to CONFIG_FILE.
while ((*new_config++ = *arg++) != 0)
;
// menu_array config_file value has to be updated when loading a new file
memmove(menu_array[menu_level].config_file, // TO
config_file, // FROM
128); //SIZE
configfile_end();
/* Never reach here. */
return 0;
}
static struct builtin builtin_call =
{
"call",
call_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"call FILE",
"Load FILE as the configuration file and return to current execution when
back command is called."
};
/* cat */
static int
cat_func (char *arg, int flags)
{
if (cat_is_on) {
int temporal_count_lines;
char c;
temporal_count_lines=count_lines; // Fetch value of count_lines
count_lines=0; // Force cat to count lines even when called from inside a
menu
if (! grub_open (arg))
return 1;
while (grub_read (&c, 1))
{
/* Because running "cat" with a binary file can confuse the terminal,
print only some characters as they are. */
//if (isspace (c) || (c >= ' ' && c <= '~'))
grub_putchar (c);
//else
//grub_putchar ('?');
}
grub_close ();
count_lines=temporal_count_lines; // Restore value of count_lines
}
return 0;
}
static struct builtin builtin_cat =
{
"cat",
cat_func,
BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"cat FILE",
"Print the contents of the file FILE."
};
/* catis [on|off] */
static int
catis_func (char *arg, int flags)
{
/* If ARG is empty, toggle the flag. */
if (! *arg)
cat_is_on = ! cat_is_on;
else if (grub_memcmp (arg, "on", 2) == 0)
cat_is_on = 1;
else if (grub_memcmp (arg, "off", 3) == 0)
cat_is_on = 0;
else
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
//grub_printf (" Internal pager is now %s\n", cat_is_on ? "on" : "off");
// We do not want to cat anything at all.
return 0;
}
static struct builtin builtin_catis =
{
"catis",
catis_func,
BUILTIN_CMDLINE | BUILTIN_MENU,
"catis [FLAG]",
"Toggle cat output mode with no argument. If FLAG is given and its value"
" is `on', turn on the mode. If FLAG is `off', turn off the mode."
};
/* chainloader */
static int
chainloader_func (char *arg, int flags)
{
int force = 0;
char *file = arg;
/* If the option `--force' is specified? */
if (substring ("--force", arg) <= 0)
{
force = 1;
file = skip_to (0, arg);
}
/* Open the file. */
if (! grub_open (file))
{
kernel_type = KERNEL_TYPE_NONE;
return 1;
}
/* Read the first block. */
if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
{
grub_close ();
kernel_type = KERNEL_TYPE_NONE;
/* This below happens, if a file whose size is less than 512 bytes
is loaded. */
if (errnum == ERR_NONE)
errnum = ERR_EXEC_FORMAT;
return 1;
}
/* If not loading it forcibly, check for the signature. */
if (! force
&& (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))
!= BOOTSEC_SIGNATURE))
{
grub_close ();
errnum = ERR_EXEC_FORMAT;
kernel_type = KERNEL_TYPE_NONE;
return 1;
}
grub_close ();
kernel_type = KERNEL_TYPE_CHAINLOADER;
/* XXX: Windows evil hack. For now, only the first five letters are
checked. */
if (IS_PC_SLICE_TYPE_FAT (current_slice)
&& ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,
"MSWIN", 5))
*((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))
= part_start;
errnum = ERR_NONE;
return 0;
}
static struct builtin builtin_chainloader =
{
"chainloader",
chainloader_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"chainloader [--force] FILE",
"Load the chain-loader FILE. If --force is specified, then load it"
" forcibly, whether the boot loader signature is present or not."
};
// let's comment cmp_func - adrian15 - it is not very useful
/* This function could be used to debug new filesystem code. Put a file
in the new filesystem and the same file in a well-tested filesystem.
Then, run "cmp" with the files. If no output is obtained, probably
the code is good, otherwise investigate what's wrong... */
/* cmp FILE1 FILE2
static int
cmp_func (char *arg, int flags)
{
// The filenames.
char *file1, *file2;
// The addresses.
char *addr1, *addr2;
int i;
// The size of the file.
int size;
// Get the filenames from ARG.
file1 = arg;
file2 = skip_to (0, arg);
if (! *file1 || ! *file2)
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
// Terminate the filenames for convenience.
nul_terminate (file1);
nul_terminate (file2);
// Read the whole data from FILE1.
addr1 = (char *) RAW_ADDR (0x100000);
if (! grub_open (file1))
return 1;
// Get the size.
size = filemax;
if (grub_read (addr1, -1) != size)
{
grub_close ();
return 1;
}
grub_close ();
// Read the whole data from FILE2.
addr2 = addr1 + size;
if (! grub_open (file2))
return 1;
// Check if the size of FILE2 is equal to the one of FILE2.
if (size != filemax)
{
grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",
size, file1, filemax, file2);
grub_close ();
return 0;
}
if (! grub_read (addr2, -1))
{
grub_close ();
return 1;
}
grub_close ();
// Now compare ADDR1 with ADDR2.
for (i = 0; i < size; i++)
{
if (addr1[i] != addr2[i])
grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n",
i, (unsigned) addr1[i], file1,
(unsigned) addr2[i], file2);
}
return 0;
}
static struct builtin builtin_cmp =
{
"cmp",
cmp_func,
BUILTIN_CMDLINE,
"cmp FILE1 FILE2",
"Compare the file FILE1 with the FILE2 and inform the different values"
" if any."
};
*/
/* color */
/* Set new colors used for the menu interface. Support two methods to
specify a color name: a direct integer representation and a symbolic
color name. An example of the latter is "blink-light-gray/blue". */
static int
color_func (char *arg, int flags)
{
char *normal;
char *highlight;
int new_normal_color;
int new_highlight_color;
static char *color_list[16] =
{
"black",
"blue",
"green",
"cyan",
"red",
"magenta",
"brown",
"light-gray",
"dark-gray",
"light-blue",
"light-green",
"light-cyan",
"light-red",
"light-magenta",
"yellow",
"white"
};
auto int color_number (char *str);
/* Convert the color name STR into the magical number. */
auto int color_number (char *str)
{
char *ptr;
int i;
int color = 0;
/* Find the separator. */
for (ptr = str; *ptr && *ptr != '/'; ptr++)
;
/* If not found, return -1. */
if (! *ptr)
return -1;
/* Terminate the string STR. */
*ptr++ = 0;
/* If STR contains the prefix "blink-", then set the `blink' bit
in COLOR. */
if (substring ("blink-", str) <= 0)
{
color = 0x80;
str += 6;
}
/* Search for the color name. */
for (i = 0; i < 16; i++)
if (grub_strcmp (color_list[i], str) == 0)
{
color |= i;
break;
}
if (i == 16)
return -1;
str = ptr;
nul_terminate (str);
/* Search for the color name. */
for (i = 0; i < 8; i++)
if (grub_strcmp (color_list[i], str) == 0)
{
color |= i << 4;
break;
}
if (i == 8)
return -1;
return color;
}
normal = arg;
highlight = skip_to (0, arg);
new_normal_color = color_number (normal);
if (new_normal_color < 0 && ! safe_parse_maxint (&normal,
&new_normal_color))
return 1;
/* The second argument is optional, so set highlight_color
to inverted NORMAL_COLOR. */
if (! *highlight)
new_highlight_color = ((new_normal_color >> 4)
| ((new_normal_color & 0xf) << 4));
else
{
new_highlight_color = color_number (highlight);
if (new_highlight_color < 0
&& ! safe_parse_maxint (&highlight, &new_highlight_color))
return 1;
}
if (current_term->setcolor)
current_term->setcolor (new_normal_color, new_highlight_color);
return 0;
}
static struct builtin builtin_color =
{
"color",
color_func,
BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
"color NORMAL [HIGHLIGHT]",
"Change the menu colors. The color NORMAL is used for most"
" lines in the menu, and the color HIGHLIGHT is used to highlight the"
" line where the cursor points. If you omit HIGHLIGHT, then the"
" inverted color of NORMAL is used for the highlighted line."
" The format of a color is \"FG/BG\". FG and BG are symbolic color names."
" A symbolic color name must be one of these: black, blue, green,"
" cyan, red, magenta, brown, light-gray, dark-gray, light-blue,"
" light-green, light-cyan, light-red, light-magenta, yellow and white."
" But only the first eight names can be used for BG. You can prefix"
" \"blink-\" to FG if you want a blinking foreground color."
};
/* configfile */
static int
configfile_func (char *arg, int flags)
{
char *new_config = config_file;
/* Check if the file ARG is present. */
if (! grub_open (arg))
return 1;
grub_close ();
/* Copy ARG to CONFIG_FILE. */
while ((*new_config++ = *arg++) != 0)
;
// menu_array config_file value has to be updated when loading a new file
memmove(menu_array[menu_level].config_file, // TO
config_file, // FROM
128); //SIZE
configfile_end();
/* Never reach here. */
return 0;
}
static struct builtin builtin_configfile =
{
"configfile",
configfile_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"configfile FILE",
"Load FILE as the configuration file."
};
/* default */
static int
default_func (char *arg, int flags)
{
#ifndef SUPPORT_DISKLESS
if (grub_strcmp (arg, "saved") == 0)
{
default_entry = saved_entryno;
return 0;
}
#endif /* SUPPORT_DISKLESS */
if (! safe_parse_maxint (&arg, &default_entry))
return 1;
return 0;
}
static struct builtin builtin_default =
{
"default",
default_func,
BUILTIN_MENU,
#if 0
"default [NUM | `saved']",
"Set the default entry to entry number NUM (if not specified, it is"
" 0, the first entry) or the entry number saved by savedefault."
#endif
};
#ifdef GRUB_UTIL
/* device */
static int
device_func (char *arg, int flags)
{
char *drive = arg;
char *device;
/* Get the drive number from DRIVE. */
if (! set_device (drive))
return 1;
/* Get the device argument. */
device = skip_to (0, drive);
/* Terminate DEVICE. */
nul_terminate (device);
if (! *device || ! check_device (device))
{
errnum = ERR_FILE_NOT_FOUND;
return 1;
}
assign_device_name (current_drive, device);
return 0;
}
static struct builtin builtin_device =
{
"device",
device_func,
BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"device DRIVE DEVICE",
"Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
" can be used only in the grub shell."
};
#endif /* GRUB_UTIL */
/* displayapm // Removed displayapm because SGD does not need it.
static int
displayapm_func (char *arg, int flags)
{
if (mbi.flags & MB_INFO_APM_TABLE)
{
grub_printf ("APM BIOS information:\n"
" Version: 0x%x\n"
" 32-bit CS: 0x%x\n"
" Offset: 0x%x\n"
" 16-bit CS: 0x%x\n"
" 16-bit DS: 0x%x\n"
" 32-bit CS length: 0x%x\n"
" 16-bit CS length: 0x%x\n"
" 16-bit DS length: 0x%x\n",
(unsigned) apm_bios_info.version,
(unsigned) apm_bios_info.cseg,
apm_bios_info.offset,
(unsigned) apm_bios_info.cseg_16,
(unsigned) apm_bios_info.dseg_16,
(unsigned) apm_bios_info.cseg_len,
(unsigned) apm_bios_info.cseg_16_len,
(unsigned) apm_bios_info.dseg_16_len);
}
else
{
grub_printf ("No APM BIOS found or probe failed\n");
}
return 0;
}
static struct builtin builtin_displayapm =
{
"displayapm",
displayapm_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"displayapm",
"Display APM BIOS information."
};
*/
/* displaymem // Display mem removed. We do not need it in SGD
static int
displaymem_func (char *arg, int flags)
{
if (get_eisamemsize () != -1)
grub_printf (" EISA Memory BIOS Interface is present\n");
if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0
|| *((int *) SCRATCHADDR) != 0)
grub_printf (" Address Map BIOS Interface is present\n");
grub_printf (" Lower memory: %uK, "
"Upper memory (to first chipset hole): %uK\n",
mbi.mem_lower, mbi.mem_upper);
if (mbi.flags & MB_INFO_MEM_MAP)
{
struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr;
int end_addr = mbi.mmap_addr + mbi.mmap_length;
grub_printf (" [Address Range Descriptor entries "
"immediately follow (values are 64-bit)]\n");
while (end_addr > (int) map)
{
char *str;
if (map->Type == MB_ARD_MEMORY)
str = "Usable RAM";
else
str = "Reserved";
grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n"
" Length: 0x%x X 4GB + 0x%x bytes\n",
str,
(unsigned long) (map->BaseAddr >> 32),
(unsigned long) (map->BaseAddr & 0xFFFFFFFF),
(unsigned long) (map->Length >> 32),
(unsigned long) (map->Length & 0xFFFFFFFF));
map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size));
}
}
return 0;
}
static struct builtin builtin_displaymem =
{
"displaymem",
displaymem_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"displaymem",
"Display what GRUB thinks the system address space map of the"
" machine is, including all regions of physical RAM installed."
};
*/
/* dd */
static int
dd_func (char *arg, int flags)
{
/* Place to put variables - Begin */
int current_size_read = 0;
/* Auxiliar variables - Begin */
int device_sector_number, size_to_read, actual_device_offset;
char *read_and_write_buffer = (char *) RAW_ADDR (0x100000);
int file_drive, file_partition, file_sector;
struct geometry file_geom;
/* Auxiliar variables - End */
/* Parse variables - Begin */
char *source_filename, *destination_device, *auxiliar_char_pointer;
int file_offset, device_offset, size_to_dd;
/* Parse variables - End */
/* Place to put variables - End */
auto void restore_file_values(void);
auto void backup_file_values(void);
auto int read_the_hard_disk_sector(void);
auto void restore_file_values(void)
{
current_drive = file_drive ;
current_partition = file_partition;
buf_geom = file_geom;
part_start = file_sector;
}
auto void backup_file_values(void)
{
file_drive = current_drive;
file_partition = current_partition;
file_geom = buf_geom;
file_sector = part_start;
}
auto int read_the_hard_disk_sector(void)
{
/* Save READ FILE variables - Begin*/
backup_file_values();
/* Save READ FILE variables - End */
if (! set_device (destination_device)
|| ! open_partition ()
|| ! devread (device_sector_number,0,SECTOR_SIZE,read_and_write_buffer))
return 0 ; // Simulate goto ddfail;
/* Restore READ FILE variables - Begin*/
restore_file_values();
/* Restore READ FILE variables - End */
return 1; // Do not do the goto ddfail;
}
int is_open = 0;
/* Parse arguments - Begin */
/* Parse filename */
source_filename = arg;
arg = skip_to (0,arg);
nul_terminate(source_filename);
/* Parse device */
destination_device = arg;
arg = skip_to (0,arg);
nul_terminate(destination_device);
/* Parse file offset */
auxiliar_char_pointer = arg;
arg = skip_to (0,arg);
if ( ! safe_parse_maxint (&auxiliar_char_pointer, &file_offset) ) return 1;
/* Parse device offset */
auxiliar_char_pointer = arg;
arg = skip_to (0,arg);
if ( ! safe_parse_maxint (&auxiliar_char_pointer, &device_offset) ) return
1;
/* Parse size */
auxiliar_char_pointer = arg;
arg = skip_to (0,arg);
if ( ! safe_parse_maxint (&auxiliar_char_pointer, &size_to_dd) ) return 1;
/* Parse arguments - End */
/* Main algorithm - Begin */
/* Prepare data - Begin */
current_size_read = 0;
/* Prepare data - End */
is_open = grub_open (source_filename);
/* Main While - Begin */
// Calculate actual_device_offset
if (device_offset < SECTOR_SIZE) actual_device_offset = device_offset ;
else actual_device_offset = device_offset % SECTOR_SIZE;
while ( current_size_read < size_to_dd ) {
grub_seek (file_offset+current_size_read);
device_sector_number = (int)((device_offset + current_size_read) /
SECTOR_SIZE ); // Let's hope that / works the same way as trunc
/* Case :0 : 1st part of the sector without changes. 2nd part from the
file. 3rd part without changes. */
if (size_to_dd < SECTOR_SIZE) {
if (!(read_the_hard_disk_sector())) goto ddfail;
size_to_read=size_to_dd;
auxiliar_char_pointer=read_and_write_buffer+actual_device_offset;
} else
{
/* Case : 1 : 1st part of the sector without changes. 2nd part read from the
file */
if ((current_size_read==0) && (actual_device_offset)) {
if (!(read_the_hard_disk_sector())) goto ddfail;
size_to_read=SECTOR_SIZE - actual_device_offset;
auxiliar_char_pointer=read_and_write_buffer+actual_device_offset;
/* Case 2: 1st part of the sector read from the file. 2nd part without
changes. */
} else {
auxiliar_char_pointer=read_and_write_buffer;
if ((current_size_read + SECTOR_SIZE)>size_to_dd) {
if (!(read_the_hard_disk_sector())) goto ddfail;
/* Let's contemplate the case device offset: 0 and size_to_dd <
SECTOR_SIZE */
if (!(actual_device_offset)) size_to_read = size_to_dd;
else size_to_read=actual_device_offset;
/* Case 3: All the sector read from the file */
} else {
/* NO NEED TO READ THE HARD DISK SECTOR FIRST */
size_to_read=SECTOR_SIZE;
}
}
}
/* Read from file - Begin */
if ( (! grub_read (auxiliar_char_pointer,size_to_read)==size_to_read)
|| (!is_open)) goto ddfail;
/* Read from file - End */
/* Save READ FILE variables - Begin*/
backup_file_values();
/* Save READ FILE variables - End */
/* Write to device - Begin */
if ( ! set_device (destination_device)
|| ! open_partition ()
|| ! devwrite (device_sector_number,1,read_and_write_buffer))
goto ddfail;
/* Restore READ FILE variables - Begin*/
restore_file_values();
/* Restore READ FILE variables - End */
/* Write to device - End */
current_size_read += size_to_read;
} // End of while
/* Main While - End */
/* If there's an error: */
ddfail:
if (is_open)
grub_close ();
disk_read_hook = 0;
#ifndef NO_DECOMPRESSION
no_decompression = 0;
#endif
return errnum;
}
static struct builtin builtin_dd =
{
"dd",
dd_func,
BUILTIN_CMDLINE,
"dd SOURCE_FILE DESTINATION_DEVICE FILE_OFFSET DEVICE_OFFSET SIZE",
"Copy SIZE bytes\n"
"FROM: SOURCE_FILE beginning at FILE_OFFSET\n"
"TO: DESTINATION_DEVICE beginning at DEVICE_OFFSET.\n"
};
/* dump FROM TO */
#ifdef GRUB_UTIL
static int
dump_func (char *arg, int flags)
{
char *from, *to;
FILE *fp;
char c;
from = arg;
to = skip_to (0, arg);
if (! *from || ! *to)
{
errnum = ERR_BAD_ARGUMENT;
return 1;
}
nul_terminate (from);
nul_terminate (to);
if (! grub_open (from))
return 1;
fp = fopen (to, "w");
if (! fp)
{
errnum = ERR_WRITE;
return 1;
}
while (grub_read (&c, 1))
if (fputc (c, fp) == EOF)
{
errnum = ERR_WRITE;
fclose (fp);
return 1;
}
if (fclose (fp) == EOF)
{
errnum = ERR_WRITE;
return 1;
}
grub_close ();
return 0;
}
static struct builtin builtin_dump =
{
"dump",
dump_func,
BUILTIN_CMDLINE,
"dump FROM TO",
"Dump the contents of the file FROM to the file TO. FROM must be"
" a GRUB file and TO must be an OS file."
};
#endif /* GRUB_UTIL */
static char embed_info[32];
/* embed */
/* Embed a Stage 1.5 in the first cylinder after MBR or in the
bootloader block in a FFS. */
static int
embed_func (char *arg, int flags)
{
char *stage1_5;
char *device;
char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
int len, size;
int sector;
stage1_5 = arg;
device = skip_to (0, stage1_5);
/* Open a Stage 1.5. */
if (! grub_open (stage1_5))
return 1;
/* Read the whole of the Stage 1.5. */
len = grub_read (stage1_5_buffer, -1);
grub_close ();
if (errnum)
return 1;
size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE;
/* Get the device where the Stage 1.5 will be embedded. */
set_device (device);
if (errnum)
return 1;
if (current_partition == 0xFFFFFF)
{
/* Embed it after the MBR. */
char mbr[SECTOR_SIZE];
char ezbios_check[2*SECTOR_SIZE];
int i;
/* Open the partition. */
if (! open_partition ())
return 1;
/* No floppy has MBR. */
if (! (current_drive & 0x80))
{
errnum = ERR_DEV_VALUES;
return 1;
}
/* Read the MBR of CURRENT_DRIVE. */
if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr))
return 1;
/* Sanity check. */
if (! PC_MBR_CHECK_SIG (mbr))
{
errnum = ERR_BAD_PART_TABLE;
return 1;
}
/* Check if the disk can store the Stage 1.5. */
for (i = 0; i < 4; i++)
if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size)
{
errnum = ERR_NO_DISK_SPACE;
return 1;
}
/* Check for EZ-BIOS signature. It should be in the third
* sector, but due to remapping it can appear in the second, so
* load and check both.
*/
if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
return 1;
if (! memcmp (ezbios_check + 3, "AERMH", 5)
|| ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
{
/* The space after the MBR is used by EZ-BIOS which we must
* not overwrite.
*/
errnum = ERR_NO_DISK_SPACE;
return 1;
}
sector = 1;
}
else
{
/* Embed it in the bootloader block in the filesystem. */
int start_sector;
/* Open the partition. */
if (! open_device ())
return 1;
/* Check if the current slice supports embedding. */
if (fsys_table[fsys_type].embed_func == 0
|| ! fsys_table[fsys_type].embed_func (&start_sector, size))
{
errnum = ERR_DEV_VALUES;
return 1;
}
sector = part_start + start_sector;
}
/* Clear the cache. */
buf_track = -1;
/* Now perform the embedding. */
if (! devwrite (sector - part_start, size, stage1_5_buffer))
return 1;
grub_printf (" %d sectors are embedded.\n", size);
grub_sprintf (embed_info, "%d+%d", sector - part_start, size);
return 0;
}
static struct builtin builtin_embed =
{
"embed",
embed_func,
BUILTIN_CMDLINE,
"embed STAGE1_5 DEVICE",
"Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE"
" is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition."
" Print the number of sectors which STAGE1_5 occupies if successful."
};
/* fallback */
static int
fallback_func (char *arg, int flags)
{
int i = 0;
while (*arg)
{
int entry;
int j;
if (! safe_parse_maxint (&arg, &entry))
return 1;
/* Remove duplications to prevent infinite looping. */
for (j = 0; j < i; j++)
if (entry == fallback_entries[j])
break;
if (j != i)
continue;
fallback_entries[i++] = entry;
if (i == MAX_FALLBACK_ENTRIES)
break;
arg = skip_to (0, arg);
}
if (i < MAX_FALLBACK_ENTRIES)
fallback_entries[i] = -1;
fallback_entryno = (i == 0) ? -1 : 0;
return 0;
}
static struct builtin builtin_fallback =
{
"fallback",
fallback_func,
BUILTIN_MENU,
#if 0
"fallback NUM...",
"Go into unattended boot mode: if the default boot entry has any"
" errors, instead of waiting for the user to do anything, it"
" immediately starts over using the NUM entry (same numbering as the"
" `default' command). This obviously won't help if the machine"
" was rebooted by a kernel that GRUB loaded."
#endif
};
/* fexists */
static int
fexists_func (char *arg, int flags)
{
if (! grub_open (arg))
return 1;
grub_close ();
return 0;
}
static struct builtin builtin_fexists =
{
"fexists",
fexists_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"fexists FILE",
"Gives an error if FILE does not exists for grub."
"Exists successfully if the file exists."
"It is useful when used in conjunction with default and fallback
commands."
};
/* find */
/* Search for the filename ARG in all of partitions. */
static int
find_func (char *arg, int flags)
{
char *filename = arg;
unsigned long drive;
unsigned long tmp_drive = saved_drive;
unsigned long tmp_partition = saved_partition;
int got_file = 0;
/* Floppies. */
for (drive = 0; drive < 8; drive++)
{
current_drive = drive;
current_partition = 0xFFFFFF;
if (open_device ())
{
saved_drive = current_drive;
saved_partition = current_partition;
if (grub_open (filename))
{
grub_close ();
grub_printf (" (fd%d)\n", drive);
got_file = 1;
}
}
errnum = ERR_NONE;
}
/* Hard disks. */
for (drive = 0x80; drive < 0x90; drive++)
{
unsigned long part = 0xFFFFFF;
unsigned long start, len, offset, ext_offset;
int type, entry;
char buf[SECTOR_SIZE];
current_drive = drive;
while (next_partition (drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
&ext_offset, buf))
{
if (type != PC_SLICE_TYPE_NONE
&& ! IS_PC_SLICE_TYPE_BSD (type)
&& ! IS_PC_SLICE_TYPE_EXTENDED (type))
{
current_partition = part;
if (open_device ())
{
saved_drive = current_drive;
saved_partition = current_partition;
if (grub_open (filename))
{
int bsd_part = (part >> 8) & 0xFF;
int pc_slice = part >> 16;
grub_close ();
if (bsd_part == 0xFF)
grub_printf (" (hd%d,%d)\n",
drive - 0x80, pc_slice);
else
grub_printf (" (hd%d,%d,%c)\n",
drive - 0x80, pc_slice, bsd_part + 'a');
got_file = 1;
}
}
}
/* We want to ignore any error here. */
errnum = ERR_NONE;
}
/* next_partition always sets ERRNUM in the last call, so clear
it. */
errnum = ERR_NONE;
}
saved_drive = tmp_drive;
saved_partition = tmp_partition;
if (got_file)
{
errnum = ERR_NONE;
return 0;
}
errnum = ERR_FILE_NOT_FOUND;
return 1;
}
static struct builtin builtin_find =
{
"find",
find_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"find FILENAME",
"Search for the filename FILENAME in all of partitions and print the list
of"
" the devices which contain the file."
};
/* selectpart */
/* Choose partitions from a hard disk with a menu */
static int
selectpart_func (char *arg, int flags)
{
unsigned long tmp_drive = saved_drive;
unsigned long tmp_partition = saved_partition;
special_menu = 1; // Force not to read the menu
if(add_menu ()) return 1;
// NEW CODE - BEGIN
// Add main title
add_choose_title ();
add_part_title ();
set_device (arg); // Saves in current_drive the hard disk
unsigned long part = 0xFFFFFF;
unsigned long start, len, offset, ext_offset;
int type, entry;
char buf[SECTOR_SIZE];
while (next_partition (current_drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
&ext_offset, buf))
{
if (type != PC_SLICE_TYPE_NONE
&& ! IS_PC_SLICE_TYPE_BSD (type)
&& ! IS_PC_SLICE_TYPE_EXTENDED (type))
{
current_partition = part;
saved_drive = current_drive;
saved_partition = current_partition;
add_part_instructions (&type, part);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "back");
// Close title
close_title ((char *) MENU_BUF, &menu_array[menu_level]);
}
// We want to ignore any error here.
errnum = ERR_NONE;
}
errnum = ERR_NONE; // We do not want that partition error makes memmove work
bad
close_menu ((char *) MENU_BUF, &menu_array[menu_level]);
// NEW CODE - END
// Define the new menu - End
saved_drive = tmp_drive;
saved_partition = tmp_partition;
configfile_end();
// Never reach here.
return 0;
}
static struct builtin builtin_selectpart =
{
"selectpart",
selectpart_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"selectpart",
"Choose partitions from a hard disk with a menu."
};
/* selectfile */
/* Choose partitions from the ones where a file is found with a menu.*/
static int
selectfile_func (char *arg, int flags)
{
char *filename=arg;
unsigned long tmp_drive = saved_drive;
unsigned long tmp_partition = saved_partition;
int got_file = 0;
int drive; // Aux variables
if (there_is_a_hard_disk ()) { errnum = ERR_FILE_NOT_FOUND; return 1; }
special_menu = 1; // Force not to read the menu
if(add_menu ()) return 1;
// NEW CODE - BEGIN
// Add main title
add_choose_title ();
add_part_title ();
while (*arg) {
filename=arg;
arg = skip_to (0,arg); // Iterate over filenames
nul_terminate (filename);
add_title (&menu_array[menu_level], "FILE: %s",filename);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "pause
Nothing to do");
close_title ((char *) MENU_BUF, &menu_array[menu_level]);
for (drive = 0x80; drive < 0x90; drive++) {
unsigned long part = 0xFFFFFF;
unsigned long start, len, offset, ext_offset;
int type, entry;
char buf[SECTOR_SIZE];
current_drive = drive;
while (next_partition (current_drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
&ext_offset, buf))
{
if (type != PC_SLICE_TYPE_NONE
&& ! IS_PC_SLICE_TYPE_BSD (type)
&& ! IS_PC_SLICE_TYPE_EXTENDED (type))
{
current_partition = part;
if (open_device ())
{
saved_drive = current_drive;
saved_partition = current_partition;
if (grub_open (filename)) {
got_file=1;
grub_close ();
add_part_instructions (&type, part);
// File instruction
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "set
out_file=%s",filename);
add_instruction (&menu_array[menu_level], (char *) MENU_BUF, "back");
// Close title
close_title ((char *) MENU_BUF, &menu_array[menu_level]);
}
}
// We want to ignore any error here.
errnum = ERR_NONE;
}
}
/* next_partition always sets ERRNUM in the last call, so clear
it. */
errnum = ERR_NONE;
} // Hard disks
errnum = ERR_NONE; // We do not want that partition error makes memmove work
bad
} // while filename
if (!got_file)
{
back_func("",1);
errnum = ERR_FILE_NOT_FOUND;
return 1;
}
close_menu ((char *) MENU_BUF, &menu_array[menu_level]);
// NEW CODE - END
// Define the new menu - End
saved_drive = tmp_drive;
saved_partition = tmp_partition;
configfile_end();
// Never reach here.
return 0;
}
static struct builtin builtin_selectfile =
{
"selectfile",
selectfile_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"selectfile",
"Choose partitions from the ones where a file is found with a menu."
};
/* findf */
/* Search for the filename ARG in all of partitions. */
static int
findf_func (char *arg, int flags)
{
char *filename = arg;
unsigned long drive;
unsigned long tmp_drive = saved_drive;
unsigned long tmp_partition = saved_partition;
int got_file = 0;
/* Hard disks. */
for (drive = 0x80; drive < 0x90; drive++)
{
unsigned long part = 0xFFFFFF;
unsigned long start, len, offset, ext_offset;
int type, entry;
char buf[SECTOR_SIZE];
char device_found[14]; // A device should fit into 14 space
current_drive = drive;
while (next_partition (drive, 0xFFFFFF, &part, &type,
&start, &len, &offset, &entry,
&ext_offset, buf))
{
if (type != PC_SLICE_TYPE_NONE
&& ! IS_PC_SLICE_TYPE_BSD (type)
&& ! IS_PC_SLICE_TYPE_EXTENDED (type))
{
current_partition = part;
if (open_device ())
{
saved_drive = current_drive;
saved_partition = current_partition;
if (grub_open (filename))
{
int bsd_part = (part >> 8) & 0xFF;
int pc_slice = part >> 16;
grub_close ();
grub_sprintf (device_found,"out_hd=hd%d",drive - 0x80);
set_func(device_found,1);
grub_sprintf (device_found,"out_part=(hd%d,%d)",drive - 0x80, pc_slice);
set_func(device_found,1);
grub_sprintf (device_found,"out_part_n=%d",pc_slice);
set_func(device_found,1);
grub_sprintf (device_found,"out_linux_end=%c%d",'a' + drive - 0x80, pc_slice
+ 1);
set_func(device_found,1);
grub_sprintf (device_found,"out_linux_letter=%c",'a' + drive - 0x80);
set_func(device_found,1);
grub_sprintf (device_found,"out_linux_number=%d", pc_slice + 1);
set_func(device_found,1);
if (bsd_part == 0xFF) {
grub_sprintf (device_found,"out_device=(hd%d,%d)",
drive - 0x80, pc_slice);
}
else
{
grub_sprintf (device_found,"out_slice=%c",bsd_part + 'a');
set_func(device_found,1);
grub_sprintf (device_found,"out_device=(hd%d,%d,%c)",
drive - 0x80, pc_slice, bsd_part + 'a');
}
set_func(device_found,1);
got_file = 1;
}
}
}
if (got_file) break;
/* We want to ignore any error here. */
errnum = ERR_NONE;
}
if (got_file) break;
/* next_partition always sets ERRNUM in the last call, so clear
it. */
errnum = ERR_NONE;
}
saved_drive = tmp_drive;
saved_partition = tmp_partition;
if (got_file)
{
errnum = ERR_NONE;
return 0;
}
errnum = ERR_FILE_NOT_FOUND;
return 1;
}
static struct builtin builtin_findf =
{
"findf",
findf_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"findf FILENAME",
"Search for the filename FILENAME in all of partitions (only hard disks)
and save"
"into out_hd, out_part, out_slice and out_device variables the drive of
the FILENAME"
};
/* graphics */
static int
gfxmenu_func (char *arg, int flags)
{
memmove(graphics_file, arg, sizeof graphics_file - 1);
graphics_file[sizeof graphics_file - 1] = 0;
return 0;
}
static struct builtin builtin_gfxmenu =
{
"gfxmenu",
gfxmenu_func,
BUILTIN_MENU | BUILTIN_HELP_LIST,
"gfxmenu FILE",
"Use the graphical menu from FILE."
};
/* graphics */
static int
gfxmenuoff_func (char *arg, int flags)
{
graphics_file[0] = 0;
return 0;
}
static struct builtin builtin_gfxmenuoff =
{
"gfxmenuoff",
gfxmenuoff_func,
BUILTIN_MENU | BUILTIN_HELP_LIST,
"gfxmenuoff",
"Turn off the graphical menu."
};
/* geometry */
static int
geometry_func (char *arg, int flags)
{
struct geometry geom;
char *msg;
char *device = arg;
#ifdef GRUB_UTIL
char *ptr;
#endif
/* Get the device number. */
set_device (device);
if (errnum)
return 1;
/* Check for the geometry. */
if (get_diskinfo (current_drive, &geom))
{
errnum = ERR_NO_DISK;
return 1;
}
/* Attempt to read the first sector, because some BIOSes turns out not
to support LBA even though they set the bit 0 in the support
bitmap, only after reading something actually. */
if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
{
errnum = ERR_READ;
return 1;
}
#ifdef GRUB_UTIL
ptr = skip_to (0, device);
if (*ptr)
{
char *cylinder, *head, *sector, *total_sector;
int num_cylinder, num_head, num_sector, num_total_sector;
cylinder = ptr;
head = skip_to (0, cylinder);
sector = skip_to (0, head);
total_sector = skip_to (0, sector);
if (! safe_parse_maxint (&cylinder, &num_cylinder)
|| ! safe_parse_maxint (&head, &num_head)
|| ! safe_parse_maxint (§or, &num_sector))
return 1;
disks[current_drive].cylinders = num_cylinder;
disks[current_drive].heads = num_head;
disks[current_drive].sectors = num_sector;
if (safe_parse_maxint (&total_sector, &num_total_sector))
disks[current_drive].total_sectors = num_total_sector;
else
disks[current_drive].total_sectors
= num_cylinder * num_head * num_sector;
errnum = 0;
geom = disks[current_drive];
buf_drive = -1;
}
#endif /* GRUB_UTIL */
#ifdef GRUB_UTIL
msg = device_map[current_drive];
#else
if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
msg = "LBA";
else
msg = "CHS";
#endif
grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
"The number of sectors = %d, %s\n",
current_drive,
geom.cylinders, geom.heads, geom.sectors,
geom.total_sectors, msg);
real_open_partition (1);
return 0;
}
static struct builtin builtin_geometry =
{
"geometry",
geometry_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]",
"Print the information for a drive DRIVE. In the grub shell, you can"
" set the geometry of the drive arbitrarily. The number of the cylinders,"
" the one of the heads, the one of the sectors and the one of the total"
" sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR,"
" respectively. If you omit TOTAL_SECTOR, then it will be calculated
based"
" on the C/H/S values automatically."
};
/* halt */
static int
halt_func (char *arg, int flags)
{
int no_apm;
no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0);
grub_halt (no_apm);
/* Never reach here. */
return 1;
}
static struct builtin builtin_halt =
{
"halt",
halt_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"halt [--no-apm]",
"Halt your system. If APM is avaiable on it, turn off the power using"
" the APM BIOS, unless you specify the option `--no-apm'."
};
/* help */
#define MAX_SHORT_DOC_LEN 39
#define MAX_LONG_DOC_LEN 66
static int
help_func (char *arg, int flags)
{
int all = 0;
if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
{
all = 1;
arg = skip_to (0, arg);
}
if (! *arg)
{
/* Invoked with no argument. Print the list of the short docs. */
struct builtin **builtin;
int left = 1;
for (builtin = builtin_table; *builtin != 0; builtin++)
{
int len;
int i;
/* If this cannot be used in the command-line interface,
skip this. */
if (! ((*builtin)->flags & BUILTIN_CMDLINE))
continue;
/* If this doesn't need to be listed automatically and "--all"
is not specified, skip this. */
if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST))
continue;
len = grub_strlen ((*builtin)->short_doc);
/* If the length of SHORT_DOC is too long, truncate it. */
if (len > MAX_SHORT_DOC_LEN - 1)
len = MAX_SHORT_DOC_LEN - 1;
for (i = 0; i < len; i++)
grub_putchar ((*builtin)->short_doc[i]);
for (; i < MAX_SHORT_DOC_LEN; i++)
grub_putchar (' ');
if (! left)
grub_putchar ('\n');
left = ! left;
}
/* If the last entry was at the left column, no newline was printed
at the end. */
if (! left)
grub_putchar ('\n');
}
else
{
/* Invoked with one or more patterns. */
do
{
struct builtin **builtin;
char *next_arg;
/* Get the next argument. */
next_arg = skip_to (0, arg);
/* Terminate ARG. */
nul_terminate (arg);
for (builtin = builtin_table; *builtin; builtin++)
{
/* Skip this if this is only for the configuration file. */
if (! ((*builtin)->flags & BUILTIN_CMDLINE))
continue;
if (substring (arg, (*builtin)->name) < 1)
{
char *doc = (*builtin)->long_doc;
/* At first, print the name and the short doc. */
grub_printf ("%s: %s\n",
(*builtin)->name, (*builtin)->short_doc);
/* Print the long doc. */
while (*doc)
{
int len = grub_strlen (doc);
int i;
/* If LEN is too long, fold DOC. */
if (len > MAX_LONG_DOC_LEN)
{
/* Fold this line at the position of a space. */
for (len = MAX_LONG_DOC_LEN; len > 0; len--)
if (doc[len - 1] == ' ')
break;
}
grub_printf (" ");
for (i = 0; i < len; i++)
grub_putchar (*doc++);
grub_putchar ('\n');
}
}
}
arg = next_arg;
}
while (*arg);
}
return 0;
}
static struct builtin builtin_help =
{
"help",
help_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"help [--all] [PATTERN ...]",
"Display helpful information about builtin commands. Not all commands"
" aren't shown without the option `--all'."
};
/* hide */
static int
hide_func (char *arg, int flags)
{
if (! set_device (arg))
return 1;
if (! set_partition_hidden_flag (1))
return 1;
return 0;
}
static struct builtin builtin_hide =
{
"hide",
hide_func,
BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
"hide PARTITION",
"Hide PARTITION by setting the \"hidden\" bit in"
" its partition type code."
};
/* initrd */
static int
initrd_func (char *arg, int flags)
{
switch (kernel_type)
{
case KERNEL_TYPE_LINUX:
case KERNEL_TYPE_BIG_LINUX:
if (! load_initrd (arg))
return 1;
break;
default:
errnum = ERR_NEED_LX_KERNEL;
return 1;
}
return 0;
}
static struct builtin builtin_initrd =
{
"initrd",
initrd_func,
BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
"initrd FILE [ARG ...]",
"Load an initial ramdisk FILE for a Linux format boot image and set the"
" appropriate parameters in the Linux setup area in memory."
};
/* install */
static int
install_func (char *arg, int flags)
{
char *stage1_file, *dest_dev, *file, *addr;
char *stage1_buffer = (char *) RAW_ADDR (0x100000);
char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
char *old_sect = stage2_buffer + SECTOR_SIZE;
char *stage2_first_buffer = old_sect + SECTOR_SIZE;
char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
/* XXX: Probably SECTOR_SIZE is reasonable. */
char *config_filename = stage2_second_buffer + SECTOR_SIZE;
char *dummy = config_filename + SECTOR_SIZE;
int new_drive = GRUB_INVALID_DRIVE;
int dest_drive, dest_partition, dest_sector;
int src_drive, src_partition, src_part_start;
int i;
struct geometry dest_geom, src_geom;
int saved_sector;
int stage2_first_sector, stage2_second_sector;
char *ptr;
int installaddr, installlist;
/* Point to the location of the name of a configuration file in Stage 2.
*/
char *config_file_location;
/* If FILE is a Stage 1.5? */
int is_stage1_5 = 0;
/* Must call grub_close? */
int is_open = 0;
/* If LBA is forced? */
int is_force_lba = 0;
/* Was the last sector full? */
int last_length = SECTOR_SIZE;
#ifdef GRUB_UTIL
/* If the Stage 2 is in a partition mounted by an OS, this will store
the filename under the OS. */
char *stage2_os_file = 0;
#endif /* GRUB_UTIL */
auto void disk_read_savesect_func (int sector, int offset, int length);
auto void disk_read_blocklist_func (int sector, int offset, int length);
/* Save the first sector of Stage2 in STAGE2_SECT. */
auto void disk_read_savesect_func (int sector, int offset, int length)
{
if (debug)
printf ("[%d]", sector);
/* ReiserFS has files which sometimes contain data not aligned
on sector boundaries. Returning an error is better than
silently failing. */
if (offset != 0 || length != SECTOR_SIZE)
errnum = ERR_UNALIGNED;
saved_sector = sector;
}
/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
INSTALLSECT. */
auto void disk_read_blocklist_func (int sector, int offset, int length)
{
if (debug)
printf("[%d]", sector);
if (offset != 0 || last_length != SECTOR_SIZE)
{
/* We found a non-sector-aligned data block. */
errnum = ERR_UNALIGNED;
return;
}
last_length = length;
if (*((unsigned long *) (installlist - 4))
+ *((unsigned short *) installlist) != sector
|| installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
{
installlist -= 8;
if (*((unsigned long *) (installlist - 8)))
errnum = ERR_WONT_FIT;
else
{
*((unsigned short *) (installlist + 2)) = (installaddr >> 4);
*((unsigned long *) (installlist - 4)) = sector;
}
}
*((unsigned short *) installlist) += 1;
installaddr += 512;
}
/* First, check the GNU-style long option. */
while (1)
{
if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
{
is_force_lba = 1;
arg = skip_to (0, arg);
}
#ifdef GRUB_UTIL
else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) ==
0)
{
stage2_os_file = arg + sizeof ("--stage2=") - 1;
arg = skip_to (0, arg);
nul_terminate (stage2_os_file);
}
#endif /* GRUB_UTIL */
else
break;
}
stage1_file = arg;
dest_dev = skip_to (0, stage1_file);
if (*dest_dev == 'd')
{
new_drive = 0;
dest_dev = skip_to (0, dest_dev);
}
file = skip_to (0, dest_dev);
addr = skip_to (0, file);
/* Get the installation address. */
if (! safe_parse_maxint (&addr, &installaddr))
{
/* ADDR is not specified. */
installaddr = 0;
ptr = addr;
errnum = 0;
}
else
ptr = skip_to (0, addr);
#ifndef NO_DECOMPRESSION
/* Do not decompress Stage 1 or Stage 2. */
no_decompression = 1;
#endif
/* Read Stage 1. */
is_open = grub_open (stage1_file);
if (! is_open
|| ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)
goto fail;
/* Read the old sector from DEST_DEV. */
if (! set_device (dest_dev)
|| ! open_partition ()
|| ! devread (0, 0, SECTOR_SIZE, old_sect))
goto fail;
/* Store the information for the destination device. */
dest_drive = current_drive;
dest_partition = current_partition;
dest_geom = buf_geom;
dest_sector = part_start;
/* Copy the possible DOS BPB, 59 bytes at byte offset 3. */
grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET,
old_sect + BOOTSEC_BPB_OFFSET,
BOOTSEC_BPB_LENGTH);
/* If for a hard disk, copy the possible MBR/extended part table. */
if (dest_drive & 0x80)
grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC,
old_sect + STAGE1_WINDOWS_NT_MAGIC,
STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC);
/* Check for the version and the signature of Stage 1. */
if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION
|| (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET))
!= BOOTSEC_SIGNATURE))
{
errnum = ERR_BAD_VERSION;
goto fail;
}
/* This below is not true any longer. But should we leave this alone? */
/* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe
routine. */
if (! (dest_drive & 0x80)
&& (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80
|| stage1_buffer[BOOTSEC_PART_OFFSET] == 0))
{
errnum = ERR_BAD_VERSION;
goto fail;
}
grub_close ();
/* Open Stage 2. */
is_open = grub_open (file);
if (! is_open)
goto fail;
src_drive = current_drive;
src_partition = current_partition;
src_part_start = part_start;
src_geom = buf_geom;
if (! new_drive)
new_drive = src_drive;
else if (src_drive != dest_drive)
grub_printf ("Warning: the option `d' was not used, but the Stage 1
will"
" be installed on a\ndifferent drive than the drive where"
" the Stage 2 resides.\n");
/* Set the boot drive. */
*((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;
/* Set the "force LBA" flag. */
*((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;
/* If DEST_DRIVE is a hard disk, enable the workaround, which is
for buggy
--
View this message in context:
http://www.nabble.com/%22partnew%22-Command-Writes-Wrong-Ending-Cylinder-in-MPT-tf2599372.html#a8998458
Sent from the Grub - Bugs mailing list archive at Nabble.com.
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Fw: "partnew" Command Writes Wrong Ending Cylinder in MPT, Steve Burtchin, 2007/02/04
- Re: "partnew" Command Writes Wrong Ending Cylinder in MPT, sburtchin, 2007/02/15