📄 builtins.c
字号:
errnum = ERR_UNRECOGNIZED; return 1; #else /* ! GRUB_UTIL */ unsigned short *port; /* Get the drive number. */ set_device (arg); if (errnum) return 1; /* Clean out IO_MAP. */ grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short)); /* Track the int13 handler. */ track_int13 (current_drive); /* Print out the result. */ for (port = io_map; *port != 0; port++) grub_printf (" 0x%x", (unsigned int) *port); return 0; #endif /* ! GRUB_UTIL */}static struct builtin builtin_ioprobe ={ "ioprobe", ioprobe_func, BUILTIN_CMDLINE, "ioprobe DRIVE", "Probe I/O ports used for the drive DRIVE."};/* kernel */static intkernel_func (char *arg, int flags){ int len; kernel_t suggested_type = KERNEL_TYPE_NONE; unsigned long load_flags = 0;#ifndef AUTO_LINUX_MEM_OPT load_flags |= KERNEL_LOAD_NO_MEM_OPTION;#endif /* Deal with GNU-style long options. */ while (1) { /* If the option `--type=TYPE' is specified, convert the string to a kernel type. */ if (grub_memcmp (arg, "--type=", 7) == 0) { arg += 7; if (grub_memcmp (arg, "netbsd", 6) == 0) suggested_type = KERNEL_TYPE_NETBSD; else if (grub_memcmp (arg, "freebsd", 7) == 0) suggested_type = KERNEL_TYPE_FREEBSD; else if (grub_memcmp (arg, "openbsd", 7) == 0) /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's point of view. */ suggested_type = KERNEL_TYPE_NETBSD; else if (grub_memcmp (arg, "linux", 5) == 0) suggested_type = KERNEL_TYPE_LINUX; else if (grub_memcmp (arg, "biglinux", 8) == 0) suggested_type = KERNEL_TYPE_BIG_LINUX; else if (grub_memcmp (arg, "multiboot", 9) == 0) suggested_type = KERNEL_TYPE_MULTIBOOT; else { errnum = ERR_BAD_ARGUMENT; return 1; } } /* If the `--no-mem-option' is specified, don't pass a Linux's mem option automatically. If the kernel is another type, this flag has no effect. */ else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) load_flags |= KERNEL_LOAD_NO_MEM_OPTION; else break; /* Try the next. */ arg = skip_to (0, arg); } len = grub_strlen (arg); /* Reset MB_CMDLINE. */ mb_cmdline = (char *) MB_CMDLINE_BUF; if (len + 1 > MB_CMDLINE_BUFLEN) { errnum = ERR_WONT_FIT; return 1; } /* Copy the command-line to MB_CMDLINE. */ grub_memmove (mb_cmdline, arg, len + 1); kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); if (kernel_type == KERNEL_TYPE_NONE) return 1; mb_cmdline += len + 1; return 0;}static struct builtin builtin_kernel ={ "kernel", kernel_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", "Attempt to load the primary boot image from FILE. The rest of the" " line is passed verbatim as the \"kernel command line\". Any modules" " must be reloaded after using this command. The option --type is used" " to suggest what type of kernel to be loaded. TYPE must be either of" " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."};/* lock */static intlock_func (char *arg, int flags){ if (! auth && password) { errnum = ERR_PRIVILEGED; return 1; } return 0;}static struct builtin builtin_lock ={ "lock", lock_func, BUILTIN_CMDLINE, "lock", "Break a command execution unless the user is authenticated."}; /* makeactive */static intmakeactive_func (char *arg, int flags){ if (! make_saved_active ()) return 1; return 0;}static struct builtin builtin_makeactive ={ "makeactive", makeactive_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "makeactive", "Set the active partition on the root disk to GRUB's root device." " This command is limited to _primary_ PC partitions on a hard disk."};/* map *//* Map FROM_DRIVE to TO_DRIVE. */static intmap_func (char *arg, int flags){ char *to_drive; char *from_drive; unsigned long to, from; int i; to_drive = arg; from_drive = skip_to (0, arg); /* Get the drive number for TO_DRIVE. */ set_device (to_drive); if (errnum) return 1; to = current_drive; /* Get the drive number for FROM_DRIVE. */ set_device (from_drive); if (errnum) return 1; from = current_drive; /* 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;}static struct builtin builtin_map ={ "map", map_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "map TO_DRIVE FROM_DRIVE", "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" " when you chain-load some operating systems, such as DOS, if such an" " OS resides at a non-first drive."};#ifdef USE_MD5_PASSWORDS/* md5crypt */static intmd5crypt_func (char *arg, int flags){ char crypted[36]; char key[32]; unsigned int seed; int i; const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRST" "UVWXYZabcdefghijklmnopqrstuvwxyz"; /* First create a salt. */ /* The magical prefix. */ grub_memset (crypted, 0, sizeof (crypted)); grub_memmove (crypted, "$1$", 3); /* Create the length of a salt. */ seed = currticks (); /* Generate a salt. */ for (i = 0; i < 8 && seed; i++) { /* FIXME: This should be more random. */ crypted[3 + i] = seedchars[seed & 0x3f]; seed >>= 6; } /* A salt must be terminated with `$', if it is less than 8 chars. */ crypted[3 + i] = '$';#ifdef DEBUG_MD5CRYPT grub_printf ("salt = %s\n", crypted);#endif /* Get a password. */ grub_memset (key, 0, sizeof (key)); get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0); /* Crypt the key. */ make_md5_password (key, crypted); grub_printf ("Encrypted: %s\n", crypted); return 0;}static struct builtin builtin_md5crypt ={ "md5crypt", md5crypt_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "md5crypt", "Generate a password in MD5 format."};#endif /* USE_MD5_PASSWORDS *//* module */static intmodule_func (char *arg, int flags){ int len = grub_strlen (arg); switch (kernel_type) { case KERNEL_TYPE_MULTIBOOT: if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) { errnum = ERR_WONT_FIT; return 1; } grub_memmove (mb_cmdline, arg, len + 1); if (! load_module (arg, mb_cmdline)) return 1; mb_cmdline += len + 1; break; case KERNEL_TYPE_LINUX: case KERNEL_TYPE_BIG_LINUX: if (! load_initrd (arg)) return 1; break; default: errnum = ERR_NEED_MB_KERNEL; return 1; } return 0;}static struct builtin builtin_module ={ "module", module_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "module FILE [ARG ...]", "Load a boot module FILE for a Multiboot format boot image (no" " interpretation of the file contents is made, so users of this" " command must know what the kernel in question expects). The" " rest of the line is passed as the \"module command line\", like" " the `kernel' command."};/* modulenounzip */static intmodulenounzip_func (char *arg, int flags){ int ret;#ifndef NO_DECOMPRESSION no_decompression = 1;#endif ret = module_func (arg, flags);#ifndef NO_DECOMPRESSION no_decompression = 0;#endif return ret;}static struct builtin builtin_modulenounzip ={ "modulenounzip", modulenounzip_func, BUILTIN_CMDLINE | BUILTIN_HELP_LIST, "modulenounzip FILE [ARG ...]", "The same as `module', except that automatic decompression is" " disabled."};/* pager [on|off] */static intpager_func (char *arg, int flags){ /* If ARG is empty, toggle the flag. */ if (! *arg) use_pager = ! use_pager; else if (grub_memcmp (arg, "on", 2) == 0) use_pager = 1; else if (grub_memcmp (arg, "off", 3) == 0) use_pager = 0; else { errnum = ERR_BAD_ARGUMENT; return 1; } grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off"); return 0;}static struct builtin builtin_pager ={ "pager", pager_func, BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, "pager [FLAG]", "Toggle pager 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."};/* partnew PART TYPE START LEN */static intpartnew_func (char *arg, int flags){ int new_type, new_start, new_len; int start_cl, start_ch, start_dh; int end_cl, end_ch, end_dh; int entry; char mbr[512]; /* Convert a LBA address to a CHS address in the INT 13 format. */ auto void lba_to_chs (int lba, int *cl, int *ch, int *dh); void lba_to_chs (int lba, int *cl, int *ch, int *dh) { int cylinder, head, sector; sector = lba % buf_geom.sectors + 1; head = (lba / buf_geom.sectors) % buf_geom.heads; cylinder = lba / (buf_geom.sectors * buf_geom.heads); if (cylinder >= buf_geom.cylinders) cylinder = buf_geom.cylinders - 1; *cl = sector | ((cylinder & 0x300) >> 2); *ch = cylinder & 0xFF; *dh = head; } /* Get the drive and the partition. */ if (! set_device (arg)) return 1; /* The drive must be a hard disk. */ if (! (current_drive & 0x80)) { errnum = ERR_BAD_ARGUMENT; return 1; } /* The partition must a primary partition. */ if ((current_partition >> 16) > 3 || (current_partition & 0xFFFF) != 0xFFFF) { errnum = ERR_BAD_ARGUMENT; return 1; } entry = current_partition >> 16; /* Get the new partition type. */ arg = skip_to (0, arg); if (! safe_parse_maxint (&arg, &new_type)) return 1; /* The partition type is unsigned char. */ if (new_type > 0xFF) { errnum = ERR_BAD_ARGUMENT; return 1; } /* Get the new partition start. */ arg = skip_to (0, arg); if (! safe_parse_maxint (&arg, &new_start)) return 1; /* Get the new partition length. */ arg = skip_to (0, arg); if (! safe_parse_maxint (&arg, &new_len)) return 1; /* Read the MBR. */ if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr)) return 1; /* Check if the new partition will fit in the disk. */ if (new_start + new_len > buf_geom.total_sectors) { errnum = ERR_GEOM; return 1; } /* Store the partition information in the MBR. */ lba_to_chs (new_start, &start_cl, &start_ch, &start_dh); lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh); PC_SLICE_FLAG (mbr, entry) = 0; PC_SLICE_HEAD (mbr, entry) = start_dh; PC_SLICE_SEC (mbr, entry) = start_cl; PC_SLICE_CYL (mbr, entry) = start_ch; PC_SLICE_TYPE (mbr, entry) = new_type; PC_SLICE_EHEAD (mbr, entry) = end_dh; PC_SLICE_ESEC (mbr, entry) = end_cl; PC_SLICE_ECYL (mbr, entry) = end_ch; PC_SLICE_START (mbr, entry) = new_start; PC_SLICE_LENGTH (mbr, entry) = new_len; /* Make sure that the MBR has a valid signature. */ PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE; /* Write back the MBR to the disk. */ buf_track = -1; if (! rawwrite (current_drive, 0, mbr)) return 1; return 0;}static struct builtin builtin_partnew ={ "partnew", partnew_func, BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, "partnew PART TYPE START LEN", "Create a primary partition at the starting address START with the" " length LEN, with the type TYPE. START and LEN are in sector units."};/* parttype PART TYPE */static intparttype_func (char *arg, int flags){ int new_type; unsigned long part = 0xFFFFFF; unsigned long start, len, offset, ext_offset; int entry, type; char mbr[512]; /* Get the drive and the partition. */ if (! set_device (arg)) return 1; /* The drive must be a hard disk. */ if (! (current_drive & 0x80)) { errnum = ERR_BAD_ARGUMENT; return 1; } /* The partition must be a PC slice. */ if ((current_partition >> 16) == 0xFF || (current_partition & 0xFFFF) != 0xFFFF) { errnum = ERR_BAD_ARGUMENT; return 1; } /* Get the new partition type. */ arg = skip_to (0, arg); if (! safe_parse_maxint (&arg, &new_type)) return 1; /* The partition type is unsigned char. */ if (new_type > 0xFF)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -